Java并发四(wait,两种模式,park)
-2022.3.28 -BDY
猛猪猪语录:请把摇摇马还给我!!!!
文章目录
前言
承接上文
一、wait和notify (重点)
1.故事简介
2.wait、notify介绍 (必须要获取到锁对象, 才能调用这些方法)
当线程0获得到了锁, 成为Monitor的Owner, 但是此时它发现自己想要执行synchroized代码块的条件不满足; 此时它就调用obj.wait方法, 进入到Monitor中的WaitSet集合, 此时线程0的状态就变为WAITING
- BLOCKED和WAITING状态区别:
- BLOCKED状态的线程是在竞争锁对象时,发现Monitor的Owner已经是别的线程了,此时就会进入EntryList中,并处于BLOCKED状态
- WAITING状态的线程是获得了对象的锁,但是自身的原因无法执行synchroized的临界区资源需要进入阻塞状态时,锁对象调用了wait方法而进入了WaitSet中,处于WAITING状态
- 处于BLOCKED状态的线程会在锁被释放的时候被唤醒
- 处于WAITING状态的线程只有被锁对象调用了notify方法(obj.notify/obj.notifyAll),才会被唤醒。然后它会进入到EntryList, 重新竞争锁 (此时就将锁升级为重量级锁)
3.API演示(重点关注小南和小女干活实例)
11:10:39.516 guizy.WaitNotifyTest [小南] - 有烟没?[false]
11:10:39.521 guizy.WaitNotifyTest [小南] - 没烟,先歇会!
11:10:39.521 guizy.WaitNotifyTest [小女] - 外卖送到没?[false]
11:10:39.521 guizy.WaitNotifyTest [小女] - 没外卖,先歇会!
11:10:40.521 guizy.WaitNotifyTest [送外卖的] - 外卖到了噢!
11:10:40.521 guizy.WaitNotifyTest [小南] - 有烟没?[false]
想想这里的输出结果,想想代码是怎样编写的
下面为简单的使用API
/**
* Description:
*
* @author guizy
* @date 2020/12/20 09:12
*/
@Slf4j(topic = "guizy.WaitNotifyTest")
public class WaitNotifyTest {
static final Object obj = new Object();
public static void main(String[] args) throws Exception {
new Thread(() -> {
synchronized (obj) {
log.debug("执行...");
try {
// 只有获得锁对象之后, 才能调用wait/notify
obj.wait(); // 此时t1线程进入WaitSet等待
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...");
}
}, "t1").start();
new Thread(() -> {
synchronized (obj) {
log.debug("执行...");
try {
obj.wait(); // 此时t2线程进入WaitSet等待
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("其它代码...");
}
}, "t2").start();
// 让主线程等两秒在执行,为了`唤醒`,不睡的话,那两个线程还没进入waitSet,主线程就开始唤醒了
Thread.sleep(1000);
log.debug("唤醒waitSet中的线程!");
// 只有获得锁对象之后, 才能调用wait/notify
synchronized (obj) {
// obj.notify(); // 唤醒waitset中的一个线程
obj.notifyAll(); // 唤醒waitset中的全部等待线程
}
}
}
13:01:36.176 guizy.WaitNotifyTest [t1] - 执行...
13:01:36.178 guizy.WaitNotifyTest [t2] - 执行...
13:01:37.175 guizy.WaitNotifyTest [main] - 唤醒waitSet中的线程!
13:01:37.175