当前位置:网站首页>多线程-线程通信(wait-notify,await-single,park-unpark)
多线程-线程通信(wait-notify,await-single,park-unpark)
2022-04-22 22:19:00 【185的阿平】
在多线程场景中,如有些线程需要依赖另外线程的结果而继续执行,如多个线程处理请求,有的处理的快有点慢。快的需要等待慢的线程结果一起提交执行结果。都会涉及到线程间的通信,就是A线程告知B线程处理的结果是怎么样,B线程再执行对应逻辑。通信比较经典的就是采用等待通知模式,当然还有join,volilate等也可作为通信手段。本文重点讲下API层面的通信。
举个例子,三个线程T1,T2,MAIN的场景,T1因为条件不满足进入等待状态,等待其他线程的唤醒(可理解为孩子吃饭没辣条自己关上门在房间里等待辣条)。T2的工作就是唤醒T1线程,但是没满足T1的条件。所以T1还是会进入等待状态(可理解为爸爸为了骗孩子吃饭去敲门叫孩子,说有辣条了,但此时其实没辣条的,所以孩子出门看了一眼,又回去房间里等待了)。MAIN线程也是唤醒线程,并且还满足T1的条件,这时T1就会正常执行。(可理解为妈妈过了一段时间看不下去了,去买了辣条并叫孩子出来吃饭,孩子出来看到有辣条了就开心的吃起来饭)
(1)基于Object的wait-notify,此方法需要与syncronized代码块共用。因为底层是采用monitor对象的waitSet去实现。
@Slf4j
class WaitNotify {
private static boolean flag = false;
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (lock) {
while (!flag) {
log.info("没辣条不想吃饭,进房间等待");
try {
lock.wait(); //释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.info("哈哈!有辣条吃饭真香");
}
},"孩子").start();
new Thread(()->{
synchronized (lock) {
log.info("爸爸给你买辣条了,出来吃饭");
lock.notify();
}
},"爸爸").start();
SleepUtils.sleep(2);
synchronized (lock) {
log.info("妈妈给你买辣条了,出来吃饭");
flag = true;
lock.notify();
}
}
}

(2)基于ReentrantLock的await,single。语法比较繁琐,需要先获取到lock,然后要建立一个休息室供线程休息,类似与monitor中的waitSet。最后需要unlock释放锁。
@Slf4j
class AwaitSingle{
private static boolean flag = false;
private static ReentrantLock lock = new ReentrantLock();
static Condition condition = lock.newCondition(); //休息室
public static void main(String[] args) {
new Thread(()-> {
lock.lock();
try {
while (!flag) {
log.info("没辣条不想吃饭,进房间等待");
try {
condition.await();//进入休息室等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.info("哈哈!有辣条吃饭真香");
} finally {
lock.unlock();
}
},"孩子").start();
new Thread(()->{
lock.lock();
try{
log.info("爸爸给你买辣条了,出来吃饭");
condition.signal(); //唤醒
} finally {
lock.unlock();
}
},"爸爸").start();
SleepUtils.sleep(2);
lock.lock();
try {
log.info("妈妈给你买辣条了,出来吃饭");
flag = true;
condition.signal();
}finally {
lock.unlock();
}
}
}
(3)基于LockSupport的park,unpark方法。此方法要注意的是如先调用unpark,则第一次park时不会被阻塞。第二次才会。但并不会unpark调了多次就可以使park失效多次,调用多次unpark也只会失效一次park。
@Slf4j
class Park{
private static boolean flag = false;
public static void main(String[] args) {
Thread t1 = new Thread(()-> {
while (!flag) {
log.info("没辣条不想吃饭,进房间等待");
LockSupport.park();
}
log.info("哈哈!有辣条吃饭真香");
},"孩子");
t1.start();
new Thread(()->{
log.info("爸爸给你买辣条了,出来吃饭");
LockSupport.unpark(t1);
},"爸爸").start();
SleepUtils.sleep(2);
log.info("妈妈给你买辣条了,出来吃饭");
flag = true;
LockSupport.unpark(t1);
}
}
版权声明
本文为[185的阿平]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_42740540/article/details/124346905
边栏推荐
- appinventor拓展开发
- GBase 8s V8. 8 SQL Guide: Tutorial - 6.2.1 (1)
- 牛客BM41. 输出二叉树的右视图
- GBase 8s V8. 8 SQL Guide: Tutorial - 6.1.2 (3)
- 九九乘法表代码
- O0 O1 O2 O3 optimization principle
- Enter a line of characters, separated by a space between words, and count how many words there are
- OJ每日一练——猴子吃桃问题
- 浅谈细说构造函数
- fastadmin 跳转后限定搜索条件
猜你喜欢
随机推荐
[MRCTF2020]Ez_bypass
Official account is configured for pseudo static to prevent page path loading.
根据这个有效方法,UI自动化测试就是那么的简单
线性基(各种模板+例题)
On the law of enterprise informatization
Multithreading advanced (7) -- optimistic lock and pessimistic lock
【 luogu】 p1162 couleur de remplissage (bfs)
cluster_acc计算
餐饮行业收银系统源码,C# .NET + MSSQL WPF
41.0:GemBox. Spreadsheet|. Document|. Pdf|. Presentation
MySql--数据库基础
Study notes 2-0417
=============
公众号配置伪静态防止出现页面路径加载问题
What is the function of timestamp and how to apply for it?
浅谈细说构造函数
处理用逗号分隔的字符串 并按字典升序排序输出
Redis应用解决问题
ACL2022 | 利用中文语言层级异质图强化预训练语言模型
High end beer is losing young people

![[summary of scattered knowledge points 5]](/img/a6/6700f00b01bc59fc0366d64071ac41.png)







