多執行緒之執行緒通訊wait和notify的使用
阿新 • • 發佈:2019-02-20
使用wait和notify方法實現執行緒之間的通訊,注意,這兩個方法是Object類的方法,也就是說Java為所有的物件都提供的這兩個方法。
1 wait和notify必須配合synchronized關鍵字使用。
2 wait方法釋放鎖,notify方法不釋放鎖。
3 還要注意一點 就是涉及到執行緒之間的通訊,就肯定會用到validate修飾。
案例:
t1執行緒向集合中不斷新增元素,當集合中元素個數為5的時候,就向t2執行緒發出通知,(當集合元素個數不等於5時候,t2執行緒處於等待狀態),然後t2向下執行,丟擲異常。
package com.wuk.Demo;
import java.util.ArrayList;
import java.util.List;
/**
* wait和notify的使用
*
* @author Administrator
*
*/
public class MyThread004 {
private static volatile List list=new ArrayList();
public void add() {
list.add("wuk");
}
public int size() {
return list.size();
}
public static void main (String[] args) {
MyThread004 list1=new MyThread004();
Object obj=new Object();
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj) {
System.out.println("t1執行緒啟動。。。。");
for (int i=0;i<10;i++) {
list1.add();
System.out.println("當前執行緒"+Thread.currentThread().getName()+"添加了一個元素");
try {
Thread.sleep(500);
if(list1.size()==5) {
System.out.println("已經發出通知。。");
obj.notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"t1");
Thread t2=new Thread (new Runnable() {
@Override
public void run() {
synchronized (obj) {
System.out.println("t2啟動。。。");
if(list1.size()!=5) {
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("當前執行緒:" + Thread.currentThread().getName() + "收到通知執行緒停止..");
throw new RuntimeException();
}
}
},"t2");
t2.start();
t1.start();
}
}
列印結果:
t2啟動。。。
t1執行緒啟動。。。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
已經發出通知。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒:t2收到通知執行緒停止..
Exception in thread "t2" java.lang.RuntimeException
at com.wuk.Demo.MyThread004$2.run(MyThread004.java:79)
at java.lang.Thread.run(Unknown Source)
分析:
首先啟動t2執行緒,使得t2執行緒處於等待狀態,然後當集合等於5的時候,t1向t2執行緒發出通知,但是並不會釋放鎖,所以當t1執行完畢後,t2執行緒才會向下執行。
分析幾種情況:
(1) 有人說 validate不是可以實現執行緒之間的可見性嗎,那麼我就不需要t1通知,當t2發現集合元素是5了就會往下執行?
去掉obj.notify(); 結果是:
t2啟動。。。
t1執行緒啟動。。。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
已經發出通知。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
分析:
因為當t2執行了wait()方法,就會處於等待狀態,如果不去喚醒他,他就會一直等待下去。
(2)如果我們先讓t1執行會是什麼結果?
t1執行緒啟動。。。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
已經發出通知。。
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
當前執行緒t1添加了一個元素
t2啟動。。。
分析:
因為notify不釋放鎖,如果t1先執行,就會先擁有鎖,那麼只有等到t1執行完畢以後,t2才會有機會執行,這時候集合長度早都不是5了,所以就會一直等待下去。