java多线程生产者与消费者问题_Java多线程详解之四:生产者消费者问题
一、问题描述
生产者消费者问题(Producer-Consumer problem),也称有限缓冲区问题(Bounded-buffer promblem),是一个多线程同步问题的经典案例。对于一个固定大小的缓冲区,有两个线程共享该缓冲区----即“生产者”和“消费者”。顾名思义,“生产者”就是往缓冲区中添加数据的线程,“消费者”就是消耗缓冲区中数据的线程。如果不加以限制,当缓冲区满了的时候,如果“生产者”继续生产,就会导致缓冲区溢出;当缓冲区为空时,“消费者”也无法消费。
一个栗子:就拿北京烤鸭来说,烤鸭子的厨师就是“生产者”,买烤鸭的顾客就是“消费者”,烤鸭子的炉子就是有限缓冲区,比如说一个炉子只能放10只鸭子,那这个缓冲区的大小就是10,鸭子就是缓冲区中的数据。当炉子里已经有10只鸭子的时候,厨师就不能再添加烤鸭了,没地方放了,就必须等待顾客来买鸭子;而当炉子里没有鸭子时,顾客就必须等待厨师烤鸭子。
二、问题核心
所以该问题主要有以下几点需要注意:
(1)在一个线程进行生产或者消费时,其余线程就不能再进行消费或者生产(线程同步)
(2)在缓冲区为满时,生产者就不能继续生产
(3)在缓冲区为空时,消费者就不能继续消费
三、Java代码实现
当缓冲区已满时,生产者线程停止执行,放弃锁,使自己处于等状态,让其他线程执行;
当缓冲区已空时,消费者线程停止执行,放弃锁,使自己处于等状态,让其他线程执行;
当生产者向缓冲区放入一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态;
当消费者从缓冲区取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态;
产品Duck.java
//产品类
classDuck{//产品编号
public intid;public Duck(intid) {this.id =id;
}
}
缓冲区Container.java
//缓冲区类
classContainer{//容器大小为10
Duck[] ducks = new Duck[10];//记录当前缓冲区数据量
int count = 0;//生产者生产
public synchronized void push(Duck duck) throwsInterruptedException {//如果满了,就需要等待消费者
if(count == 10){this.wait(); //生产者等待
this.notifyAll(); //通知消费者消费
}//如果没满,就将生产的产品放入缓冲区
System.out.println("正在生产第"+duck.id+"只烤鸭");
ducks[count++] =duck;//通知消费者消费
this.notifyAll();
}//消费者消费
public synchronized Duck pop() throwsInterruptedException {//如果为空,就等生产者
if(count == 0){this.wait(); //消费者等待
this.notifyAll(); //唤醒消费者
}//如果不空就消费
count--;
Duck duck=ducks[count];
System.out.println("正在消费第"+duck.id+"只烤鸭");//通知生产者生产
this.notifyAll();returnduck;
}
}
生产者Producer.java
class Producer extendsThread{private Container container; //缓冲区
publicProducer(Container container){this.container =container;
}
@Overridepublic voidrun() {for (int i = 0; i < 20; i++) {
Duck duck= newDuck(i);try{
Thread.sleep(10);
container.push(duck);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者Consumer.java
class Consumer extendsThread{private Container container; //缓冲区
publicConsumer(Container container){this.container =container;
}
@Overridepublic voidrun() {for (int i = 0; i < 20; i++) {try{
Thread.sleep(100);
Duck duck=container.pop();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
主方法:
public static voidmain(String[] args) {//创建一个缓冲区对象
Container container = newContainer();//创建生产者,消费对象
Producer producer = new Producer(container); //生产者
Consumer consumer = newConsumer(container);//开启线程
producer.start();
consumer.start();
}
注:wait()表示线程一直等待,直到其他线程唤醒该线程,并且该线程会释放对象得锁;
notifyAll()是唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度;
欢迎关注微信公众号,不定期分享学习笔记与资料,与Mike一起学java,谢谢~
java多线程生产者与消费者问题_Java多线程详解之四:生产者消费者问题相关推荐
- java按照io流向基类_Java IO详解
1 Java IO流的概念,分类 1.1 Java IO流的概念 java的IO是实现输入和输出的基础,可以方便的实现数据的输入和输出操作.在java中把不同的输入/输出源(键盘,文件,网络连接等)抽 ...
- 操作系统之多线程编程—读者优先/写者优先详解
操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...
- 深入浅出多线程编程实战(五)ThreadLocal详解(介绍、使用、原理、应用场景)
深入浅出多线程编程实战(五)ThreadLocal详解(介绍.使用.原理.应用场景) 文章目录 一.ThreadLocal简介 二.ThreadLocal与Synchronized区别 三.Threa ...
- java中sleep()、wait()相同与不同详解
java中sleep().wait()相同与不同详解 相同 java中Thread#sleep和Object#wait方法都是暂停当前线程,当前线程让出CPU占用.并不存在调用sleep后还占用CPU ...
- 蓝桥杯 Java B组 省赛决赛模拟赛 详解及小结汇总+题目下载【2013年(第4届)~2021年(第12届)】
蓝桥杯 Java B组 省赛决赛模拟赛 详解及小结汇总+题目下载[2013年(第4届)~2021年(第12届)] 百度网盘-CSDN蓝桥杯资料(真题PDF+其它资料) 提取码:6666 2013年 ...
- Java中的宏变量,宏替换详解。
转载自 Java中的宏变量,宏替换详解. 群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 输出true false 来看下面这段程序,和群友分享的大致一样. public static vo ...
- java加密算法入门(三)-非对称加密详解
1.简单介绍 这几天一直在看非对称的加密,相比之前的两篇内容,这次看了两倍多的时间还云里雾里的,所以这篇文章相对之前的两篇,概念性的东西多了些,另外是代码的每一步我都做了介绍,方便自己以后翻阅,也方便 ...
- java的数组与Arrays类源码详解
java的数组与Arrays类源码详解 java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名Arrays调用. 类的 ...
- Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载)
Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载) 说明:主要是针对一些中大型的项目需要进行分布式以及负载均衡的架构提一些思路与建议. 面对大量用户访问.高并发请求,海量 ...
最新文章
- 语言中如何在main函数开始前执行函数
- Linux下命令行安装weblogic10.3.6
- 实时监控:基于流计算 Oceanus ( Flink ) 实现系统和应用级实时监控
- winserver2016 401您无权使用所提供的凭据查看此目录或页面_不用找了,30分钟帮你搞定使用 Spring Cloud 和 Docker 轻松构建微服务架构!...
- 漫步线性代数十二——网络
- 7.FreeRTOS学习笔记-事件
- 最新一二线城市知名 IT 互联网公司名单出炉!
- 读取文件,解决中文乱码问题
- C/S打包 客户端/windows程序 Inno Setup
- idea Mac格式化代码快捷键
- 唐太宗李世民14个儿子的可悲结局[高清组图]
- 用java编写人民币转化为美元_js实现数字转人民币、美元的大写汉字
- windows屏幕亮度调节失灵的解决方法
- HttpClient上传文件到微信素材乱码问题解决
- S7-300/400 PLC 模拟量输入/输出的量程转换
- 关于腾讯微博之死,离职员工所了解的真相
- F2FS源码分析-1.2 [F2FS 元数据布局部分] Superblock结构
- 人脸验证(二)--DeepID
- css flex布局 —— 容器属性 flex-wrap
- thinkphp官方类库
热门文章
- Linux培训之系统升级
- Hibernate简介2
- 设计模式学习(十六) 模板方法模式
- Android draw9patch点九图常识
- ShineTime - 带有 CSS3 闪亮特效的缩略图相册
- 需要注意的小问题------闹的笑话
- CDataBaseEngineSink::OnRequestPlatformParameter 数据库异常:查询超时已过期 [ 0x80040e31 ]...
- sql之left join、right join、inner join的区别,连接自己时的查询结果测试
- flask蓝图的使用
- Vue.js 由 1 到 2 的旅程 - (1)