多线程之线程通信wait和notify的使用
使用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了,所以就会一直等待下去。
还没有评论,来说两句吧...