使用wait和notify方法实现线程之间的通信,注意,这两个方法是Object类的方法,也就是说Java为所有的对象都提供的这两个方法。
1 wait和notify必须配合synchronized关键字使用。
2 wait方法释放锁,notify方法不释放锁。
3 涉及到线程之间的通信,就肯定会用到 volatile 修饰。
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: 13213
* @Date: 2020/11/16 10:12
* @Description:
*/
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(list1.size());
System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
throw new RuntimeException();
}
}
}, "t2");
t2.start();
t1.start();
}
}
结果:
分析:
首先启动t2线程,之后t2线程处于等待状态,然后当集合等于5的时候,t1向t2线程发出通知,但是并不会释放锁,所以当t1执行完毕后,t2线程才会向下执行。
若先启动t1线程,则运行结果如下:
分析:
因为notify不释放锁,如果t1先执行,就会先拥有锁,那么只有等到t1执行完毕以后,t2才会有机会执行,这时候集合长度早都不是5了,所以就会一直等待下去。