一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
优雅的完成线程间的通信
保护暂停模式
定义
-
即 Guarded Suspension,用在一个线程等待另一个线程的执行结果要点
-
有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
-
如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)
-
JDK 中,join 的实现、Future 的实现,采用的就是此模式
-
因为要等待另一方的结果,因此归类到同步模式
step1,下载百度首页资源
step2,实现带超时的等待
扩展1: join方法源码
注意:当线程执行结束之后在 jdk底层会调用 notifyall
扩展2: 实现多任务版本
图中 Futures 就好比居民楼一层的信箱(每个信箱有房间编号),左侧的 t0,t2,t4 就好比等待邮件的居民,右侧的 t1,t3,t5 就好比邮递员
如果需要在多个类之间使用 GuardedObject 对象,作为参数传递不是很方便,因此设计一个用来解耦的中间类,
这样不仅能够解耦【结果等待者】和【结果生产者】,还能够同时支持多个任务的管理
生产者/消费者模式
1. 定义
-
与前面的保护性暂停中的 GuardObject 不同,不需要产生结果和消费结果的线程一一对应
-
消费队列可以用来平衡生产和消费的线程资源
-
生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据
-
消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据
-
JDK 中各种阻塞队列,采用的就是这种模式
20:56:47.939 c.MessageQueue [生产者1] - 已生产消息 Message{id=1, value=值1}
20:56:47.943 c.MessageQueue [生产者0] - 已生产消息 Message{id=0, value=值0}
20:56:47.944 c.MessageQueue [生产者2] - 队列已满, 生产者线程等待 20:56:48.948 c.MessageQueue [消费者] - 已消费消息 Message{id=1, value=值1}
20:56:48.948 c.MessageQueue [生产者2] - 已生产消息 Message{id=2, value=值2}
20:56:49.952 c.MessageQueue [消费者] - 已消费消息 Message{id=0, value=值0}
20:56:50.957 c.MessageQueue [消费者] - 已消费消息 Message{id=2, value=值2}
20:56:51.962 c.MessageQueue [消费者] - 队列为空, 消费者线程等待