生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。

这里实现如下情况的生产--消费模型:

生产者不断交替地生产两组数据“姓名--1 --> 内容--1”,“姓名--2--> 内容--2”,消费者不断交替地取得这两组数据,这里的“姓名--1”和“姓名--2”模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容。

由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:

1、假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系在一起;

2、生产者生产了若干次数据,消费者才开始取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。

问题1很明显要靠同步来解决,问题2则需要线程间通信,生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用wait/notify机制来实现。

详细的实现代码如下:

  1. class Info{ // 定义信息类
  2. private String name = "name";//定义name属性,为了与下面set的name属性区别开
  3. private String content = "content" ;// 定义content属性,为了与下面set的content属性区别开
  4. private boolean flag = true ;   // 设置标志位,初始时先生产
  5. public synchronized void set(String name,String content){
  6. while(!flag){
  7. try{
  8. super.wait() ;
  9. }catch(InterruptedException e){
  10. e.printStackTrace() ;
  11. }
  12. }
  13. this.setName(name) ;    // 设置名称
  14. try{
  15. Thread.sleep(300) ;
  16. }catch(InterruptedException e){
  17. e.printStackTrace() ;
  18. }
  19. this.setContent(content) ;  // 设置内容
  20. flag  = false ; // 改变标志位,表示可以取走
  21. super.notify();
  22. }
  23. public synchronized void get(){
  24. while(flag){
  25. try{
  26. super.wait() ;
  27. }catch(InterruptedException e){
  28. e.printStackTrace() ;
  29. }
  30. }
  31. try{
  32. Thread.sleep(300) ;
  33. }catch(InterruptedException e){
  34. e.printStackTrace() ;
  35. }
  36. System.out.println(this.getName() +
  37. " --> " + this.getContent()) ;
  38. flag  = true ;  // 改变标志位,表示可以生产
  39. super.notify();
  40. }
  41. public void setName(String name){
  42. this.name = name ;
  43. }
  44. public void setContent(String content){
  45. this.content = content ;
  46. }
  47. public String getName(){
  48. return this.name ;
  49. }
  50. public String getContent(){
  51. return this.content ;
  52. }
  53. }
  54. class Producer implements Runnable{ // 通过Runnable实现多线程
  55. private Info info = null ;      // 保存Info引用
  56. public Producer(Info info){
  57. this.info = info ;
  58. }
  59. public void run(){
  60. boolean flag = true ;   // 定义标记位
  61. for(int i=0;i<10;i++){
  62. if(flag){
  63. this.info.set("姓名--1","内容--1") ;    // 设置名称
  64. flag = false ;
  65. }else{
  66. this.info.set("姓名--2","内容--2") ;    // 设置名称
  67. flag = true ;
  68. }
  69. }
  70. }
  71. }
  72. class Consumer implements Runnable{
  73. private Info info = null ;
  74. public Consumer(Info info){
  75. this.info = info ;
  76. }
  77. public void run(){
  78. for(int i=0;i<10;i++){
  79. this.info.get() ;
  80. }
  81. }
  82. }
  83. public class ThreadCaseDemo03{
  84. public static void main(String args[]){
  85. Info info = new Info(); // 实例化Info对象
  86. Producer pro = new Producer(info) ; // 生产者
  87. Consumer con = new Consumer(info) ; // 消费者
  88. new Thread(pro).start() ;
  89. //启动了生产者线程后,再启动消费者线程
  90. try{
  91. Thread.sleep(500) ;
  92. }catch(InterruptedException e){
  93. e.printStackTrace() ;
  94. }
  95. new Thread(con).start() ;
  96. }
  97. }

执行结果如下:

另外,在run方法中,二者循环的次数要相同,否则,当一方的循环结束时,另一方的循环依然继续,它会阻塞在wait()方法处,而等不到对方的notify通知。

【Java并发编程】:生产者—消费者模型的更多相关文章

  1. Java 并发编程 生产者消费者模式

    本文部分摘自<Java 并发编程的艺术> 模式概述 在线程的世界里,生产者就是生产数据的线程,消费者就是消费数据的数据.生产者和消费者彼此之间不直接通信,而是通过阻塞队列进行通信,所以生产 ...

  2. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  3. Java多线程-并发协作(生产者消费者模型)

    对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓 ...

  4. Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)

    生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...

  5. Java实现多线程生产者消费者模型及优化方案

    生产者-消费者模型是进程间通信的重要内容之一.其原理十分简单,但自己用语言实现往往会出现很多的问题,下面我们用一系列代码来展现在编码中容易出现的问题以及最优解决方案. /* 单生产者.单消费者生产烤鸭 ...

  6. 网络编程 生产者消费者模型 GiL

    守护进程: 注意事项: 1.必须在p.start()前 2.守护进程不能开子进程 3.如果主进程的运行时间快于子进程,那么就只有主进程的结果,没有守护进程的结果,因为守护进程没有进行完.反之会得到两个 ...

  7. java并发之生产者消费者模型

    生产者和消费者模型是操作系统中经典的同步问题.该问题最早由Dijkstra提出,用以演示它提出的信号量机制. 经典的生产者和消费者模型的描写叙述是:有一群生产者进程在生产产品.并将这些产品提供给消费者 ...

  8. Java并发编程、内存模型与Volatile

    http://www.importnew.com/24082.html  volatile关键字 http://www.importnew.com/16142.html  ConcurrentHash ...

  9. Java多线程编程——生产者-消费者模式(1)

    生产者-消费者模式在生活中非常常见.就拿我们去餐馆吃饭为例.我们会遇到以下两种情况: 1.厨师-客人 如下图所示,生产者.消费者直接进行交互. 生产者生产出产品后,通知消费者:消费者消费后,通知生产者 ...

  10. c++并发练习---生产者消费者模型

    问题:有一个生产者,多个消费者,生产者每生产一个,放入队列,多个消费者顺序从队列中取出数据,打印最终结果. 分析:首先这题,我本意应该设计成如下模型:生产者单开一个线程,向队列中放入数据,而消费者在锁 ...

随机推荐

  1. BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4266  Solved: 2616[Submit][Statu ...

  2. Chrome报错:跨域问题处理( Access-Control-Allow-Origin)_ 用于本地测试的快捷解决方法

    报错提示如下: XMLHttpRequest cannot load http://www.xxxx.com/264/Data/GetScreenInfo. No 'Access-Control-Al ...

  3. Nvidia显卡驱动下载

    https://www.nvidia.cn/Download/index.aspx?lang=cn https://blog.csdn.net/weixin_39643690/article/deta ...

  4. Ubuntu14.04下安装Cuda8.0

    https://blog.csdn.net/sinat_19628145/article/details/60475696 https://developer.nvidia.com/cuda-down ...

  5. (并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )

    http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others)    Memo ...

  6. (KMP扩展 利用循环节来计算) Cyclic Nacklace -- hdu -- 3746

    http://acm.hdu.edu.cn/showproblem.php?pid=3746 Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others ...

  7. hdu 4950 打怪

    http://acm.hdu.edu.cn/showproblem.php?pid=4950 给定怪兽血量h,你攻击力a,怪物回血力b,你攻击k次要休息一次,问能否杀死怪兽 特判一次打死怪兽的情况和第 ...

  8. WC Java 实现

    项目 github 地址 一. 实现情况 基本要求 c 统计文件字符数 (实现) w 统计文件词数 (实现) l 统计文件行数(实现) 扩展功能 s 递归处理目录下符合条件得文件(实现) a 返回文件 ...

  9. .NET在IE10下的回传BUG修复

    以前我也没注意到,直到有次公司新配了台机器做测试服务器,在测试过程中意外发现凡是涉及PostBack的操作仅在IE10下都无效,其他版本浏览器都没有问题,本机调试也没有问题. 这也就是说在程序相同的情 ...

  10. asp.net excel导出功能

    以下是我在项目开发中所做的关于Excel导出功能,不足之处还望大家指正,相互学习 protected void btn_Export_Click(object sender, EventArgs e) ...