《重新学习多线程》 -- 保护暂停模式以及生产者消费者模式

450 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

优雅的完成线程间的通信

保护暂停模式

定义

  • 即 Guarded Suspension,用在一个线程等待另一个线程的执行结果要点

  • 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject

  • 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)

  • JDK 中,join 的实现、Future 的实现,采用的就是此模式

  • 因为要等待另一方的结果,因此归类到同步模式

image.png

step1,下载百度首页资源

carbon (11).png

step2,实现带超时的等待

carbon (12).png

扩展1: join方法源码

image.png

注意:当线程执行结束之后在 jdk底层会调用 notifyall

扩展2: 实现多任务版本

图中 Futures 就好比居民楼一层的信箱(每个信箱有房间编号),左侧的 t0,t2,t4 就好比等待邮件的居民,右侧的 t1,t3,t5 就好比邮递员

如果需要在多个类之间使用 GuardedObject 对象,作为参数传递不是很方便,因此设计一个用来解耦的中间类,

这样不仅能够解耦【结果等待者】和【结果生产者】,还能够同时支持多个任务的管理

image.png

carbon (13).png

生产者/消费者模式

1. 定义

  • 与前面的保护性暂停中的 GuardObject 不同,不需要产生结果和消费结果的线程一一对应

  • 消费队列可以用来平衡生产和消费的线程资源

  • 生产者仅负责产生结果数据,不关心数据该如何处理,而消费者专心处理结果数据

  • 消息队列是有容量限制的,满时不会再加入数据,空时不会再消耗数据

  • JDK 中各种阻塞队列,采用的就是这种模式

image.png

carbon (14).png

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 [消费者] - 队列为空, 消费者线程等待