java多线程之消费者生产者模式

1/*@author shijin 2* 生产者与消费者模型中,要保证以下几点: 3* 1 同一时间内只能有一个生产者生产 生产方法加锁sychronized 4* 2 同一时间内只能有一个消费者消费 消费方法加锁sychronized 5* 3 生产者生产的同时消费者不能消费 生产方法加锁sychronized 6* 4 消费者消费的同时生产者不能生产 消费方法加锁sychronized 7* 5 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行 8* 6 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行 9*/ 10 11//主类 12class ProducerConsumer 13{ 14 public static void main(String[] args) 15 { 16 StackBasket s = new StackBasket(); 17 Producer p = new Producer(s); 18 Consumer c = new Consumer(s); 19 Thread tp = new Thread(p); 20 Thread tc = new Thread(c); 21 tp.start(); 22 tc.start(); 23 } 24} 25 26// 27class Mantou 28{ 29 private int id; 30 31 Mantou(int id){ 32 this.id = id; 33 } 34 35 public String toString(){ 36 return "Mantou :" + id; 37 } 38} 39 40//共享栈空间 41class StackBasket 42{ 43 Mantou sm[] = new Mantou[6]; 44 int index = 0; 45 46 /** 47 * show 生产方法. 48 * show 该方法为同步方法,持有方法锁; 49 * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费; 50 * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态, 51 * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费 52 * @param m 元素 53 * @return 没有返回值 54 */ 55 56 public synchronized void push(Mantou m){ 57 try{ 58 while(index == sm.length){ 59 System.out.println("!!!!!!!!!生产满了!!!!!!!!!"); 60 this.wait(); 61 } 62 this.notify(); 63 }catch(InterruptedException e){ 64 e.printStackTrace(); 65 }catch(IllegalMonitorStateException e){ 66 e.printStackTrace(); 67 } 68 69 sm[index] = m; 70 index++; 71 System.out.println("生产了:" + m + " 共" + index + "个馒头"); 72 } 73 74 /** 75 * show 消费方法 76 * show 该方法为同步方法,持有方法锁 77 * show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产; 78 * show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态 79 * show 等消费结束释放同步方法锁后生产才能持有该锁进行生产 80 * @param b true 表示显示,false 表示隐藏 81 * @return 没有返回值 82 */ 83 public synchronized Mantou pop(){ 84 try{ 85 while(index == 0){ 86 System.out.println("!!!!!!!!!消费光了!!!!!!!!!"); 87 this.wait(); 88 } 89 this.notify(); 90 }catch(InterruptedException e){ 91 e.printStackTrace(); 92 }catch(IllegalMonitorStateException e){ 93 e.printStackTrace(); 94 } 95 index--; 96 System.out.println("消费了:---------" + sm[index] + " 共" + index + "个馒头"); 97 return sm[index]; 98 } 99} 100 101class Producer implements Runnable 102{ 103 StackBasket ss = new StackBasket(); 104 Producer(StackBasket ss){ 105 this.ss = ss; 106 } 107 108 /** 109 * show 生产进程. 110 */ 111 public void run(){ 112 for(int i = 0;i < 20;i++){ 113 Mantou m = new Mantou(i); 114 ss.push(m); 115// System.out.println("生产了:" + m + " 共" + ss.index + "个馒头"); 116// 在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱 117 try{ 118 Thread.sleep((int)(Math.random()*500)); 119 }catch(InterruptedException e){ 120 e.printStackTrace(); 121 } 122 } 123 } 124} 125 126class Consumer implements Runnable 127{ 128 StackBasket ss = new StackBasket(); 129 Consumer(StackBasket ss){ 130 this.ss = ss; 131 } 132 133 /** 134 * show 消费进程. 135 */ 136 public void run(){ 137 for(int i = 0;i < 20;i++){ 138 Mantou m = ss.pop(); 139// System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头"); 140// 同上 在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱 141 try{ 142 Thread.sleep((int)(Math.random()*1000)); 143 }catch(InterruptedException e){ 144 e.printStackTrace(); 145 } 146 } 147 } 148}
点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

一种极致性能的缓冲队列

本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。背景在多线程下的生产者消费者模型中,需求满足如下情况:对生产者生产投递数据的性能要求非常高多个生产者,单个(多个也可以,本文只介绍单个的情况)消费者当消费者跟不上生产者速度时,可容忍少部分数据丢失生产者是单条单条地生产数据举个日志采集的例子,日志在不同的

一 java线程的等待/通知模型

java中线程之间的通信问题,有这么一个模型:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程。前者是生产者,后者就是消费者,也可以叫做生产者消费者问题生产者生产了产品,如何通知消费者?下面就介绍下java线程中的等待通知机制。其它语言类似,自行研究。代码附上下面是以买小

Linux系统 Centos7 环境基于Docker部署Rocketmq服务

消息队列基本概述MQ,MessageQueue,基于TCP协议构建的简单协议,区别于具体的通信协议。基于通信协议定义和抽象的更高层次的通信模型,一般都是生产者和消费者模型,又或者说服务端和客户端模型。生产者/消费者模型:一般通过定义生产者和消费者实现消息通信从而屏

3.rabbitmq

rabbitmq发布订阅模式模型组成一个消费者Producer,一个交换机Exchange,多个消息队列Queue,多个消费者Consumer一个生产者,多个消费者,每一个消费者都有自己的一个队列,生产者没有将消息直接发送到队列,而是发送到了交换机,每个队列绑定交换机,生产者发送

ActiveMQ消息队列详解

activemq消息队列,分为生产者和消费者。.1创建生产者publicclassProducter{//ActiveMq的默认用户名privatestaticfinalStringUSERNAMEActiveMQConnection.DEFAULT\_USER;//ActiveMq的默认登录密码pr