1.场景
有些时候需要两个或两个以上的线程协同工作,每个线程需要使用其他线程产生数据。

2.详细说明
可以把上面的场景抽象成生产者和消费者模式。从消费者的角度:消费者需要消费生产者生成的产品。
从生产者的角度:生产者需要将生产的产品安全地交给消费者。这虽然看着是一个简单的操作。但如果生产者和消费者在不同的线程中运行,两者之间的处理速度差异会引起问题:消费者消费的速度远快于生产者生产的速度即消费者想要获取数据,而数据还没有产生,或者消费者消费的速度远慢于生产者生产的速度即生产者想要交付数据时,消费者还处在无法接收数据的状态。

3.Producer-Consumer模式
Producer-Consumer模式在生产者和消费者中间加入”桥梁角色”。利用该角色来消除不同线程间的处理速度的差异。


要实现上述的场景,我们设计这样一个场景:
在一家制作蛋糕店里,糕点师制作蛋糕,并将蛋糕放在桌子上。顾客按顺序从桌子上拿蛋糕吃。、
说明:1.桌子上最多只能放3个蛋糕;2.若桌子已经放满3个蛋糕,糕点师必须等到桌子空出位置才能放置蛋糕;3.如果桌子上没有蛋糕,顾客必须等待桌子上有蛋糕才能吃。

因此我们需要设计4个类:糕点师类MakerThread,顾客类EaterThread,桌子类Table,启动线程的主类Main。类图如下:

源码如下:

public class Table {private final String[] buffer;private int tail;//下次put的位置private int head;//下次take的位置private int count;//buffer中蛋糕的个数public Table(int count){this.buffer=new String[count];this.head=0;this.tail=0;this.count=0;}//放置产品(蛋糕)public synchronized void addCake(String cake) throws InterruptedException {StdOut.println(Thread.currentThread().getName()+" puts "+cake);while(count>=buffer.length){wait();}buffer[tail]=cake;tail=(tail+1)%buffer.length;count++;notifyAll();}//拿取蛋糕public  synchronized String reduceCake() throws InterruptedException{while(count<=0){wait();}String cake=buffer[head];head=(head+1)%buffer.length;count--;notify();StdOut.println(Thread.currentThread().getName()+" takes "+cake);return cake;}}

在Table类中我们采用数组来存放蛋糕,同时设计两个方法:addCake()和reduceCake()来对桌子上蛋糕数量等状态进行修改。
在addCake()中线程的守护条件是:count>=buffer.length;如果满足该条件则表示桌子已放满蛋糕,糕点师需要等待,直到桌子空出位置,才能放置。
在reduceCake()中线程的守护条件是:count<=0;如果满足该条件则表示桌子已经没有蛋糕了,顾客需要等待,等到桌子上有蛋糕时才能吃。

糕点师类:

public class MakerThread extends Thread {private final Random random;private final Table table;private static int id=0;//蛋糕的流水号public MakerThread(String name,Table table,long seed){super(name);this.table=table;this.random=new Random(seed);}public void run(){try {while(true){Thread.sleep(random.nextInt(1000));String cake="[ Cake No."+nextId()+" by "+getName()+" ]";table.addCake(cake);}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private static synchronized int nextId(){return id++;}
}

顾客吃蛋糕类:

public class EaterThread extends Thread {private final Random random;private final Table table;public EaterThread(String name,Table table,long seed){super(name);this.table=table;this.random=new Random(seed);}public void run(){try {while(true){Thread.sleep(random.nextInt(1000));String cake=table.reduceCake();}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

启动线程类:

public class Main {public static void main(String[] args) {// TODO Auto-generated method stubTable table=new Table(3);//创建一个能放置3个蛋糕的桌子new MakerThread("MakerThread-1", table, 31415).start();new MakerThread("MakerThread-2", table, 31415).start();new MakerThread("MakerThread-3", table, 31415).start();new EaterThread("EaterThread-1", table, 161415).start();new EaterThread("EaterThread-2", table, 71415).start();new EaterThread("EaterThread-3", table, 81415).start();}
}

说明:学习《图解java多线程设计模式》的学习笔记整理和自己的理解。

更多技术干货,请关注下面二维码:

Java多线模式-Producer-Consumer模式(生产者、消费者模式)相关推荐

  1. java consumed_Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的 真实世界中的生产者消费者模式 生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系.比如一个人正在准备食物(生产者),而另一个人正在吃(消费者) ...

  2. Java并发编程实战~生产者-消费者模式

    前面我们在<Worker Thread 模式>中讲到,Worker Thread 模式类比的是工厂里车间工人的工作模式.但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域,就 ...

  3. java 消费者模式 多线程_[Java并发-24-并发设计模式] 生产者-消费者模式,并发提高效率...

    生产者 - 消费者模式在编程领域的应用非常广泛,前面我们曾经提到,Java 线程池本质上就是用生产者 - 消费者模式实现的,所以每当使用线程池的时候,其实就是在应用生产者 - 消费者模式. 当然,除了 ...

  4. java 生产者消费者模式_聊聊并发(十)生产者消费者模式

    本文首发于InfoQ   作者:方腾飞  校对:张龙 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使 ...

  5. 聊聊并发——生产者消费者模式

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  6. delphi生产者消费者模式代码_并发设计模式:生产者-消费者模式,并发提高效率...

    生产者 - 消费者模式在编程领域的应用非常广泛,前面我们曾经提到,Java 线程池本质上就是用生产者 - 消费者模式实现的,所以每当使用线程池的时候,其实就是在应用生产者 - 消费者模式. 当然,除了 ...

  7. 聊聊并发(10)生产者消费者模式

    微信公众号:javafirst 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 ...

  8. 聊聊并发 生产者消费者模式

    http://ifeve.com/producers-and-consumers-mode/ 本文首发于InfoQ   作者:方腾飞  校对:张龙 在并发编程中使用生产者和消费者模式能够解决绝大多数并 ...

  9. 生产者消费者模式剖析

    转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(十)生产者消费者模式 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序 ...

  10. 生产者消费者模式详细解读

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

最新文章

  1. linux 进程等待 wait 、 waitpid
  2. 2017中国电商峰会共话“一带一路”网上商机
  3. ElasticSearch客户端注解使用介绍
  4. python 表格格式输出_Python笔记---DAY3:格式化输出、for循环、列表操作
  5. 挺住!锤子新机研发停滞、全部机型官网无货 电商平台降价促销...
  6. iframe调用父页面方法_5.1 vue中子组件调用父组件的方法,务必理解自定义事件的重要性...
  7. C#中获得窗体的句柄
  8. PHP+node采集58微聊聊天信息
  9. windows pe安装系统
  10. 360浏览器打不开html5文件,为什么电脑总是打不开360浏览器
  11. FairyGUI进阶-滑动列表 虚拟列表 循环列表
  12. (3)数据链数层——计算机网络复习笔记
  13. 【论文翻译】CN-DBpedia: A Never-Ending Chinese Knowledge Extraction System
  14. SpringBoot添加压力测试
  15. JSP核心——分页查询
  16. 一个效率很高的汉字转拼音首字母的函数(未测试)
  17. uva12325(分类枚举)
  18. android singleTask
  19. 《802.11无线网络权威指南》摘录
  20. java例外站点添加不上,java例外站点添加不了

热门文章

  1. 阿里云高可用-容灾解决方案
  2. Keil 5出现Error: L6218E: Undefined symbol解决方法
  3. 处理错误:ORA-27101: shared memory realm does not exist 解决方案
  4. 从Java 8中的java.util.stream.Stream检索列表
  5. 如何按PHP中给定键的值对关联数组进行排序?
  6. IMDB是否提供API? [关闭]
  7. Djando 的 cmd命令
  8. GeoServer基础教程(三):部署发布Shapefile地图数据
  9. 如何用课件制作工具演示面积一定的矩形
  10. 实现Qemu aarch32虚拟开发板ping www.baidu.com