博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生产者消费者模型
阅读量:6037 次
发布时间:2019-06-20

本文共 3518 字,大约阅读时间需要 11 分钟。

hot3.png

这个是java线程学习里面比较经典的一个模型,描述的是多个线程之间同步与让步的问题

 

情景:

        角色1:产品->窝头

        角色2:产品容器->桶

        角色3:生产者->生产窝头->放在桶里

        角色4:消费者->从桶里拿出窝头->吃掉

 

上代码:

public class ProducerConsumer { public static void main(String[] args){  SynStack ss=new SynStack();  Producer p=new Producer(ss);  Consumer c=new Consumer(ss);  new Thread(p,"Producer1").start();  new Thread(c,"Consumer").start(); }}/** * 窝头 *   volador * */class WoTo{ int id; WoTo(int id){  this.id=id; }  public String toString(){  return "WoTo :"+this.id; }}/** * 装窝头的桶 *   volador * */class SynStack{ int index=0; WoTo[] arrWT=new WoTo[6];  /**  * 往桶里塞一个窝头  * @param wt  */ public synchronized void push(WoTo wt){  while(index == arrWT.length){    try {    this.wait();   //窝头满了,先停会   } catch (InterruptedException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }  }  this.arrWT[index]=wt;  this.index++;  this.notify();  //弄好窝头了,赶紧叫醒那些等吃的人来吃 }  /**  * 从桶里拿出一个窝头  *    */ public synchronized WoTo pop(){  while(this.index==0){   try {    this.wait(); //没窝头了,先睡会   } catch (InterruptedException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }  }  this.notify();   //窝头吃掉了,叫醒那个弄窝头的,赶紧弄窝头去  this.index--;  return this.arrWT[index];   }}/** * 生产者,生产窝头 *   volador * */class Producer implements Runnable{  SynStack ss=null; Producer(SynStack ss){  this.ss=ss; } @Override public void run() {  // TODO Auto-generated method stub  for(int i=0;i<20;i++){   //只生产20个窝头   WoTo wt=new WoTo(i);   ss.push(wt);   System.out.println("生产了:"+wt);   try {    Thread.sleep((int)Math.random()*1000);   //累了,小睡一会   } catch (InterruptedException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }  } }}/** * 消费者,专门吃窝头的 *   volador * */class Consumer implements Runnable{ SynStack ss=null; Consumer(SynStack ss){  this.ss=ss; } @Override public void run() {  // TODO Auto-generated method stub  for(int i=0;i<20;i++){   //只吃20个窝头   WoTo wt=this.ss.pop();   System.out.println("消费了:"+wt);   try {    Thread.sleep((int)Math.random()*1000);  //吃了1个,小睡一会     } catch (InterruptedException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }  } }}

 

运行结果:

 

消费了:WoTo :0

生产了:WoTo :0
消费了:WoTo :1
生产了:WoTo :1
消费了:WoTo :2
生产了:WoTo :2
消费了:WoTo :3
生产了:WoTo :3
生产了:WoTo :4
消费了:WoTo :4
生产了:WoTo :5
消费了:WoTo :5
生产了:WoTo :6
消费了:WoTo :6
生产了:WoTo :7
消费了:WoTo :7
生产了:WoTo :8
消费了:WoTo :8
生产了:WoTo :9
消费了:WoTo :9
生产了:WoTo :10
消费了:WoTo :10
生产了:WoTo :11
消费了:WoTo :11
生产了:WoTo :12
消费了:WoTo :12
生产了:WoTo :13
消费了:WoTo :13
生产了:WoTo :14
消费了:WoTo :14
生产了:WoTo :15
消费了:WoTo :15
生产了:WoTo :16
消费了:WoTo :16
生产了:WoTo :17
消费了:WoTo :17
生产了:WoTo :18
消费了:WoTo :18
生产了:WoTo :19
消费了:WoTo :19

 

由于生产者,消费者睡的时间差不多,就出现这种生产一个就吃掉一个的现象。

上面有几点东西要注意:

1.从桶里面放窝头跟从桶里面拿窝头出来必须要同步,设想一下,假如一个生产者生产了一个窝头,并往桶里面放了,下一步准备更新桶里面的窝头数,与此同时,一个吃窝头的家伙也进了桶里,在生产者添加记录数之前,把窝头给吃了,生产者还不知情,好吧,一个窝头就这样离奇消失了、、

2.生产者或者消费者要操作桶里的窝头前先要检测窝头数量情况,这里一定要用while循环去检测,不能用if,因为if判断完后还会往下面执行,都没窝头了还执行什么??

3.生产者或者消费者发现桶里的情况不对的时候要睡一下觉,同时把锁让出来给别人。这里要用wait方法睡觉,这个方法睡了,它就会把这个对象上的锁让出来,让别的等待在这个对象上的线程能拿到这把钥匙继续进行操作,记住,wait后要记得用notify把他叫醒。

 

分析下这个模式的运行:

首先生成桶、生产者、消费者。然后生产者、消费者同时开始工作,一个不停地往桶里面加窝头,另一个不停地从桶里面拿包子,吃掉。生产者使用桶的时候,拿到了桶的对象锁,消费者就不能动桶了。桶里消费者使用桶的生产者也不能动桶。ok,假如生产者比较积极,很快就把桶装满了,消费者还没来得及吃掉,这时,生产者就会用wait方法睡觉,等消费者吃了,再继续工作。注意,生产者在睡的同时要把桶的对象锁让出来,要不你死占着锁,消费者进不了桶,怎么吃?这就是为什么要用wait方法睡觉的原因了,他在睡前会把锁让出来。ok,继续,生产者总不能一直睡下去吧,消费者吃完了怎么办?所以,消费者在吃了后,桶有空间了,就要调用notify,摇一下铃,叫醒正在睡觉的生产者,让他起床造窝头。同理假如消费者比较贪吃,很快吃完了,也会睡觉,生产者造了窝头之后,也会用notify叫醒正在睡觉的消费者起床吃东西了。然后一直这样循环,知道搞定20个窝头,程序退出。

 

wait必须要synchronized里面调用才有效、、、、

转载于:https://my.oschina.net/volador/blog/78870

你可能感兴趣的文章
Vue2.5笔记:Vue的实例与生命周期
查看>>
论JVM爆炸的几种姿势及自救方法
查看>>
联合体、结构体简析
查看>>
使用throw让服务器端与客户端进行数据交互[Java]
查看>>
java反射与代理
查看>>
深度分析Java的ClassLoader机制(源码级别)
查看>>
微服务架构选Java还是选Go - 多用户负载测试
查看>>
我的友情链接
查看>>
Javascript中的异步如何实现回调
查看>>
halcon算子介绍
查看>>
挖掘你不知道的windowsxp中的带宽潜能
查看>>
Software Engineering 招聘要求
查看>>
【转载】InstallAnyWhere自动化制作安装包的知识
查看>>
69、iSCSI共享存储配置实战
查看>>
文本编程
查看>>
乔布斯走了。你还期待苹果吗?
查看>>
优先级
查看>>
Tomcat与Web服务器、应用服务器的关系
查看>>
用DFS实现全排列 & 八皇后问题
查看>>
深度学习博客
查看>>