转载;https://www.cnblogs.com/ch-forever/p/10752499.html
- 结论
- 所有对象都会有一个wait set,用于存放调用了该对象wait方法之后进入block状态的线程;
- 线程被notify之后,不一定会立即执行;
- 线程从wait set中唤醒的顺序不一定是FIFO;
- 线程被唤醒后,必须重新获取锁。
- 举例
public class WaitSet {
private final static Object lock = new Object();
/**
* 1. 所有对象都会有一个wait set,用于存放调用了该对象wait方法之后进入block状态的线程
* 2. 线程被notify之后,不一定会立即执行
* 3. 线程从wait set中唤醒的顺序不一定是FIFO
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
IntStream.rangeClosed(1, 10).forEach(i->{
new Thread(String.valueOf(i)){
@Override
public void run() {
synchronized (lock){
try {
System.out.println(Thread.currentThread().getName() + " will come to wait");
lock.wait();
System.out.println(Thread.currentThread().getName() + " will leave to wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
});
// 让主线程暂停3秒,让所有的线程进入等待状态,再逐个进行唤醒
TimeUnit.SECONDS.sleep(3);
// 逐个唤醒线程
IntStream.rangeClosed(1, 10).forEach(i->{
synchronized (lock){
lock.notify();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
输出结果:
注意:线程notify之后的操作
wait执行完,被其他线程唤醒的时候,需要再次去抢锁,且在其wait的时候会记录此时的地址,下次被唤醒抢到锁资源的时候就执行从记录的地址出向下执行。