【Java并发编程】:生产者—消费者模型
生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。
这里实现如下情况的生产--消费模型:
生产者不断交替地生产两组数据“姓名--1 --> 内容--1”,“姓名--2--> 内容--2”,消费者不断交替地取得这两组数据,这里的“姓名--1”和“姓名--2”模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容。
由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:
1、假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系在一起;
2、生产者生产了若干次数据,消费者才开始取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。
问题1很明显要靠同步来解决,问题2则需要线程间通信,生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用wait/notify机制来实现。
详细的实现代码如下:
- class Info{ // 定义信息类
- private String name = "name";//定义name属性,为了与下面set的name属性区别开
- private String content = "content" ;// 定义content属性,为了与下面set的content属性区别开
- private boolean flag = true ; // 设置标志位,初始时先生产
- public synchronized void set(String name,String content){
- while(!flag){
- try{
- super.wait() ;
- }catch(InterruptedException e){
- e.printStackTrace() ;
- }
- }
- this.setName(name) ; // 设置名称
- try{
- Thread.sleep(300) ;
- }catch(InterruptedException e){
- e.printStackTrace() ;
- }
- this.setContent(content) ; // 设置内容
- flag = false ; // 改变标志位,表示可以取走
- super.notify();
- }
- public synchronized void get(){
- while(flag){
- try{
- super.wait() ;
- }catch(InterruptedException e){
- e.printStackTrace() ;
- }
- }
- try{
- Thread.sleep(300) ;
- }catch(InterruptedException e){
- e.printStackTrace() ;
- }
- System.out.println(this.getName() +
- " --> " + this.getContent()) ;
- flag = true ; // 改变标志位,表示可以生产
- super.notify();
- }
- public void setName(String name){
- this.name = name ;
- }
- public void setContent(String content){
- this.content = content ;
- }
- public String getName(){
- return this.name ;
- }
- public String getContent(){
- return this.content ;
- }
- }
- class Producer implements Runnable{ // 通过Runnable实现多线程
- private Info info = null ; // 保存Info引用
- public Producer(Info info){
- this.info = info ;
- }
- public void run(){
- boolean flag = true ; // 定义标记位
- for(int i=0;i<10;i++){
- if(flag){
- this.info.set("姓名--1","内容--1") ; // 设置名称
- flag = false ;
- }else{
- this.info.set("姓名--2","内容--2") ; // 设置名称
- flag = true ;
- }
- }
- }
- }
- class Consumer implements Runnable{
- private Info info = null ;
- public Consumer(Info info){
- this.info = info ;
- }
- public void run(){
- for(int i=0;i<10;i++){
- this.info.get() ;
- }
- }
- }
- public class ThreadCaseDemo03{
- public static void main(String args[]){
- Info info = new Info(); // 实例化Info对象
- Producer pro = new Producer(info) ; // 生产者
- Consumer con = new Consumer(info) ; // 消费者
- new Thread(pro).start() ;
- //启动了生产者线程后,再启动消费者线程
- try{
- Thread.sleep(500) ;
- }catch(InterruptedException e){
- e.printStackTrace() ;
- }
- new Thread(con).start() ;
- }
- }
执行结果如下:
另外,在run方法中,二者循环的次数要相同,否则,当一方的循环结束时,另一方的循环依然继续,它会阻塞在wait()方法处,而等不到对方的notify通知。
【Java并发编程】:生产者—消费者模型的更多相关文章
- Java 并发编程 生产者消费者模式
本文部分摘自<Java 并发编程的艺术> 模式概述 在线程的世界里,生产者就是生产数据的线程,消费者就是消费数据的数据.生产者和消费者彼此之间不直接通信,而是通过阻塞队列进行通信,所以生产 ...
- 第23章 java线程通信——生产者/消费者模型案例
第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...
- Java多线程-并发协作(生产者消费者模型)
对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓 ...
- Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)
生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...
- Java实现多线程生产者消费者模型及优化方案
生产者-消费者模型是进程间通信的重要内容之一.其原理十分简单,但自己用语言实现往往会出现很多的问题,下面我们用一系列代码来展现在编码中容易出现的问题以及最优解决方案. /* 单生产者.单消费者生产烤鸭 ...
- 网络编程 生产者消费者模型 GiL
守护进程: 注意事项: 1.必须在p.start()前 2.守护进程不能开子进程 3.如果主进程的运行时间快于子进程,那么就只有主进程的结果,没有守护进程的结果,因为守护进程没有进行完.反之会得到两个 ...
- java并发之生产者消费者模型
生产者和消费者模型是操作系统中经典的同步问题.该问题最早由Dijkstra提出,用以演示它提出的信号量机制. 经典的生产者和消费者模型的描写叙述是:有一群生产者进程在生产产品.并将这些产品提供给消费者 ...
- Java并发编程、内存模型与Volatile
http://www.importnew.com/24082.html volatile关键字 http://www.importnew.com/16142.html ConcurrentHash ...
- Java多线程编程——生产者-消费者模式(1)
生产者-消费者模式在生活中非常常见.就拿我们去餐馆吃饭为例.我们会遇到以下两种情况: 1.厨师-客人 如下图所示,生产者.消费者直接进行交互. 生产者生产出产品后,通知消费者:消费者消费后,通知生产者 ...
- c++并发练习---生产者消费者模型
问题:有一个生产者,多个消费者,生产者每生产一个,放入队列,多个消费者顺序从队列中取出数据,打印最终结果. 分析:首先这题,我本意应该设计成如下模型:生产者单开一个线程,向队列中放入数据,而消费者在锁 ...
随机推荐
- Windows could not set the offline local information.Error code:0X80000001解决方法
我的笔记本是联想Y460(白色) 昨天在重装系统的时候遇到如下错误:Windows could not set the offline local information.Error code:0X8 ...
- JVM,Java虚拟机基础知识新手入门教程(超级通熟易懂)
作者:请叫我红领巾,转载请注明出处http://www.cnblogs.com/xxzhuang/p/7453746.html,简书地址:http://www.jianshu.com/p/b963b3 ...
- ScrollView嵌套listview ,滚动问题。设置listview不滚动
对于ListView内部的ListView,一般用来展示少量的列表数据. 内部的ListView的高度看起来是一个固定值且无法滑动,这个就比较蛋疼了.. 提供两种解决方案,方案的核心都是重新设置内部L ...
- HDU6027 Easy Summation 2017-05-07 19:02 23人阅读 评论(0) 收藏
Easy Summation Time Limit: 2000/1000 MS ...
- PBOCIC读芯片卡流程
https://blog.csdn.net/kxd_ysheng/article/details/21178101?_t=t PBOCIC读芯片卡流程,参考上面的博客,整理了一下PBOCIC卡读流程. ...
- 二、安装并配置Kubernetes Master节点
1. 安装配置Master节点上的Kubernetes服务 1.1 安装Master节点上的Kubernetes服务 yum -y install kubernetes 1.2 修改kube-apis ...
- 基于CORS的GeoServer跨域访问策略
GeoServer的跨域访问问题,有多种解决方法,本文介绍一种基于CORS的GeoServer跨域访问方法. CORS简介 CORS是一个W3C标准,全称是"跨域资源共享"(Cro ...
- Alwayson--辅助副本状态
1. 同步中(SYNCHRONIZING),主副本和辅助副本之间存在数据差异,并正在进行同步: 2. 已同步(SYNCHRONIZED),主副本和辅助副本之间不存在数据差异,无需要同步的日志: 3. ...
- ASP.Net Core 2.2 MVC入门到基本使用系列 (一)
本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...
- Oracle数据库中 to_date()与24小时制表示法及mm分钟的显示
一.在使用Oracle的to_date函数来做日期转换时,时候也许会直接的采用“yyyy-MM-dd HH:mm:ss”的格式作为格式进行转换,但是在Oracle中会引起错误:“ORA 01810 ...