Java线程之1.4版多生产多消费者示例(三)
来源:互联网 发布:oracle数据触发器 编辑:程序博客网 时间:2024/06/05 08:46
多生产者,多消费者
从单生产者单消费者示例进化而来
注意两个变化的地方:
- 为判断标记任务循环体的if—->while
- 为避免死锁唤醒notify–>notifyAll
分析下(if+notifty)的安全隐患
- tp0先开锁获取CPU执行权 生产:1 然后flag=true, 唤醒进程缓冲池(),退出
- 然后如果tp0,tp1再获得CPU执行资格,但是判断flag=true,进入缓冲池(tp0,tp1)
- 然后tc0获取CPU执行权,消费:1 然后flag=false,唤醒缓冲池(tp0,tp1),退出,假设唤醒的tp1
- 然后假如tc0,tc1想获取执行资格,判断flag = false,进入缓冲池(tp0,tc0,tc1)
- 此时已经唤醒的tp1并不会再去判断flag标识,继续向下执行,那么就出现了多生产无消费的情况
同理,1生产多消费的情况也可能发生
如果是按照单线程(while+notify)来
- 假如tp0先开锁获取CPU执行权 生产:1 然后flag=true, 唤醒进程缓冲池(),退出
- 然后如果tp0,tp1再获得CPU执行资格,但是判断flag=true,进入缓冲池(tp0,tp1)
- 然后tc0获取CPU执行权,消费:1 然后flag=false,唤醒缓冲池(tp0,tp1),退出,假设唤醒的tp1
- 然后假如tc0,tc1想获取执行资格,判断flag = false,进入缓冲池(tp0,tc0,tc1)
- 然后假如tp1执行,生产:2 同样flag=true ,
- 假如唤醒缓冲池中的是tp0而不是消费者tc0或者tc1,那么tp0和tp1判断后也会wait,这样最后4个进程都没有notify来唤醒,进入死锁
将if()改为while后可以让进程在wait后醒来再次判断flag
notifyAll可以避免出现死锁,但是会造成效率低下
*/
class Resource{ String name; private int count = 1; String id ; private boolean flag = false;//初始默认没有产品 public synchronized void producer(String name) { while(flag) try{wait();} catch (InterruptedException ex){} this.name = name; id = name + count++; System.out.println(Thread.currentThread().getName()+"--->生产:"+id); flag = true; notifyAll(); } public synchronized void consumer() { while(!flag) try{wait();} catch (InterruptedException ex){} System.out.println(Thread.currentThread().getName()+"--------->消费"+id); flag = false; notifyAll(); }}class Producer implements Runnable{ Resource r; Producer(Resource r) { this.r = r; } public void run() { while(true) { r.producer("包子"); } }}class Consumer implements Runnable{ Resource r; Consumer(Resource r) { this.r = r; } public void run() { while (true) { r.consumer(); } }}class ThreadPC2{ public static void main(String[] args) { //创建资源 Resource r = new Resource(); //创建线程任务 Producer p0 = new Producer(r); Producer p1 = new Producer(r); Consumer c0 = new Consumer(r); Consumer c1 = new Consumer(r); //创建线程 Thread tp0 = new Thread(p0); Thread tp1 = new Thread(p1); Thread tc0 = new Thread(c0); Thread tc1 = new Thread(c1); //开启线程 tp0.start(); tp1.start(); tc0.start(); tc1.start(); }}
1 0
- Java线程之1.4版多生产多消费者示例(三)
- Java多线程编程之多生产多消费者示例
- Java线程之单生产者单消费者示例(二)
- java线程:并发协作的经典之生产消费者模型
- 黑马程序员_JavaSE基础14 之 线程间通信 等待唤醒机制 多生产多消费者 ...
- Thread线程之 多生产者与多消费者模拟生产消费
- 原版线程通信之生产消费者模式
- 线程池-生产消费者
- Java线程之1.5版新特性多生产者多消费者(四)
- Java生产消费者模式之项目实践
- 多线程之生产消费者【经典例子java】
- 多线程之多生产多消费者
- Java线程同步:生产者-消费者 模型(代码示例)
- linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题
- linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题
- Java线程(三)----线程协作-生产者/消费者问题
- 【JAVA之多线程】7.生产消费示例
- Java线程机制的浅析 生产/消费者模式 LinkedBlockingQueue
- iOS 贝塞尔曲线和CAShapeLayer 结合使用的进度条详解
- JS中创建函数的三种方式及区别
- moehydrogen.SchoolOlympiadProject
- 为Docker容器设置固定IP实现网络联通(2)——通过Python脚本实现并解决pipework缺陷
- error MSB8031 Building an MFC project for a non-Unicode character set is deprecated.
- Java线程之1.4版多生产多消费者示例(三)
- go Type Identical &Value Assignability & Type Conversions
- ASCLL码表
- Loadrunner中Throughput(吞吐量)的分析与计算
- 添加、获取cookie
- 在幼儿园管理系统中,会议管理>申请会议模块:添加会议记录(提交表单)的时候报:404错误!
- java之redis篇(spring-data-redis整合)(很好)
- php、ThinkPHP禁用浏览器缓存
- ios使用友盟分享到QQ/微信时时如何判断手机上是否安装了QQ以及微信的客户端