package sync;
import java.util.ArrayList;
import java.util.List;
public class WaitAndNotify {
private volatile static List list= new ArrayList();
private void add() {
list.add("wang");
}
private int size() {
return list.size();
}
public static void main(String[] args) {
final WaitAndNotify list1 = new WaitAndNotify();
/*
* 1. 实例化一个Object对象当作锁,下面t1和t2竞争这把锁实现同步
* 2. Object下面会有wait、notify方法,(面试经常问:Object下面有哪些方法,)
* 3. 说明每个对象都有这两个方法,都可以当作锁
*/
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized (lock) {
for(int i = 0; i < 10; i++) {
list1.add();
System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素");
Thread.sleep(500);
if(list1.size() == 5) {
System.out.println("已经发出通知..");
//notify不释放锁,for循环还会继续执行
lock.notify();
}
}
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
/*
* 如果先执行t2线程,如果size不是5,就wait
* wait会释放锁
*/
if(list1.size() != 5) {
try {
System.out.println("t2进入..");
Thread.sleep(3000);
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
//
System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + "list size = 5,线程停止");
throw new RuntimeException();
}
}
}, "t2");
t2.start();
t1.start();
}
}
输出结果:
t2进入.. 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 已经发出通知.. 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程:t1添加了一个元素 当前线程收到通知:t2list size = 5,线程停止 Exception in thread "t2" java.lang.RuntimeException at sync.WaitAndNotify$2.run(WaitAndNotify.java:73) at java.lang.Thread.run(Unknown Source)
代码解读:
第一步:执行t2线程,进入run方法,list.size不等于5,就lock.wait释放锁,t2进程等待,转而执行t1
第二步:执行t1进程,得到锁,执行for循环,当list.size等于5时,发出通知..唤醒t2进程,但是会继续执行完for循环,因为notify不释放锁
第三步:t2进程被唤醒,因此list.size已经等于10,不等于5,直接输出最后两行代码
原文:https://www.cnblogs.com/Donnnnnn/p/9074552.html