本文章收录于《JAVA并发编程》合集中,本篇来介绍线程间通信,线程间通信 使线程成为一个整体,提高系统之间的 交互性,在提高CPU利用率的同时可以对线程任务进行有效的把控与监督 。
比如:多线程之间交替执行,多线程按顺序执行等,都需要使用线程通信技术,通过本篇文章您可以获得:
什么是线程通信,有什么作用
线程通信的三种实现方式
notifyAll的虚假唤醒问题,notify死锁问题
通过 ReentrantLock 实现精确唤醒
多线程按顺序执行的四种方案
线程通信常见面试题解析
相信你还有更多方式实现线程通信?不妨评论区告诉我们吧,高频率码字不易,觉得文章不错记得点赞支持一下哦!
线程间通信线程之间的交互我们称之为线程通信【Inter-Thread Communication,简称ITC】,指多个线程处理同一资源,但是任务不同
比如:小明放假在家,肚子饿了,如果发现没有吃的就会喊:妈,我饿了,弄点吃的,如果妈妈发现没有吃的了就会做菜,通知小明吃饭,总之:有菜通知小明吃饭,没菜小明通知妈妈做饭,简直吃货一个
此时就是两个线程对饭菜这同一资源有不同的任务,妈妈线程就是做饭,小明线程是吃饭,如果想要实现上边的场景,就需要妈妈线程和小明线程之间通信
要实现线程之间通信一般有三种方法:
- 使用Object对象锁的wait()、notify()和notifyAll()方法
- 使用Java5新增的JUC中的ReentrantLock结合Condition
- 使用JUC中的CountDownLatch【计数器】
饭菜资源:
public class KitChenRoom {// 是否有吃的private boolean hasFood = false;// 设置同步锁,做饭和吃饭只能同时有一个在执行,不能边做边吃private Object lock = new Object();// 做饭public void cook() {// 加锁synchronized (lock) {// 如果有吃的,就不做饭if(hasFood) {// 还有吃的,先不做饭try {lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}// 否则就做饭,System.out.println(Thread.currentThread().getName() + "没吃的了,给娃做饭!");// 做好之后,修改为truehasFood = true;// 通知其他线程吃饭lock.notifyAll();}}// 吃饭public void eat() {synchronized (lock) {// 如果没吃的,就喊妈妈做饭,暂时吃不了if (!hasFood) {try {lock.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}// 否则就吃饭System.out.println(Thread.currentThread().getName() + "感谢老妈,恰饭,恰饭");// 吃完之后,修改为falsehasFood = false;// 通知其他线程吃饭lock.notifyAll();}}}
测试类:public class KitChenMain {public static void main(String[] args) {// 创建饭菜对象KitChenRoom chenRoom = new KitChenRoom();// 创建妈妈线程,做饭new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.cook();}},"妈妈线程:").start();// 创建小明线程,吃饭new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.eat();}},"小明线程:").start();}}
运行结果:发现两个线程交替执行,没饭的时候妈妈做饭,有饭的时候小明就恰饭文章插图
虚假唤醒在wait方法的源码注释中有这么一段话:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop翻译:在单参数版本中,中断和虚假唤醒是可能的,并且该方法应始终在循环中使用
文章插图
比如上边的 饭菜资源 代码中我们使用的是if判断是否有吃的
文章插图
如果此时我们再开启一个大明线程吃饭,开启一个爸爸线程做饭,此时会发生什么问题呢
改造测试类:再开启一个大明线程和一个爸爸线程
public class KitChenMain {public static void main(String[] args) {KitChenRoom chenRoom = new KitChenRoom();// 创建妈妈线程new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.cook();}},"妈妈线程:").start();// 创建小明线程new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.eat();}},"小明线程:").start();// 爸爸线程:做饭new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.cook();}},"爸爸线程:").start();// 大明线程:吃饭new Thread(() -> {for (int i = 0; i < 5; i++) {chenRoom.eat();}},"大明线程:").start();}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一个水煮鸡蛋白的热量
- 重庆|3条私密视频外泄!景甜你糊涂呀,张柏芝阿娇的血泪教训你不懂吗
- 夏文汐|香港知名女星突然宣布复出,疑与富商丈夫离婚,多次被传和小鲜肉搞暧昧
- 景甜|3条私密视频外泄!景甜你糊涂呀,张柏芝阿娇的血泪教训你不懂吗
- 隐婚|大瓜!已婚男星与85后女闺蜜关系不纯,早先隐婚便于乱搞
- 隐婚|曝翻红男星婚后乱搞,与85花闺蜜乱玩,隐婚多年因方便约会
- 隐婚|大瓜!曝已婚翻红男星与85后女闺蜜关系不纯,早先隐婚便于乱搞
- |处于上升期的职场年轻人,到底该不该搞副业?
- 电影|何莉莉:你们笑我是风月片女王,我笑你们不懂70亿港币是有多重!
- 一个胡萝卜的热量