java java生产者消费者模式 消费者问题

当前访客身份:游客 [
当紧箍咒系到头上,任何人都能至尊宝变身齐天大圣!
:引用来自“贤狼罗兰斯”的评论”仅仅应用于 可以...
:引用来自“一万”的评论第一个问题,不是很明白了...
:引用来自“一万”的评论我可以大概讨论一下第二个...
:第一个问题,不是很明白了,猜想是不是有历史原因...
:我可以大概讨论一下第二个问题,楼主的翻译是对的...
:本事就支持啊,不用解决就行哦。。
:博主,“从saveAsFile(path) 生成的结果中提取数...
:引用来自“我是it爱好者”的评论netstat -apn | ...
:netstat -apn | grep 60000这个60000的端口号你是...
今日访问:36
昨日访问:375
本周访问:1434
本月访问:1121
所有访问:114778
生产者消费者问题理解与Java实现
发表于2年前( 18:08)&&
阅读(1007)&|&评论()
0人收藏此文章,
生产者消费者问题(英语:),也称有限缓冲问题(英语:),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。
Java代码模拟生产者消费者 产品类
package org.dennist.thread.
Product.java
public class Product {
private int productId = 0;
public Product(int productId){
this.productId = productId;
public int getProductId() {
return productId;
public void setProductId(int productId) {
this.productId = productId;
public String toString() {
return ""+productId;
package org.dennist.thread.
public class StoreHouse {
private int base = 0;
private int top = 0;
//仓库大小
private Product[] products = new Product[10];
* 生产产品
* @param product
public synchronized void push(Product product){
if(top==products.length){
//如果仓库已满,等待消费
System.out.println("仓库已满,正在等待消费..");
}catch (InterruptedException e) {
System.out.println("stop push product because other reasons");
//仓库未满,将生产的产品入库
products[top] =
//库中产品数量+1
* 消费产品
public synchronized Product pop() {
Product product =
while (top == base) {
//仓库未空,不能消费
System.out.println("仓库已空,正等待生产...");
} catch (InterruptedException e) {
System.out.println("stop push product because other reasons");
//仓库未空,等待消费
product = products[top];
products[top] =
package org.dennist.thread.
public class Producer implements Runnable{
private String producerN
private StoreHouse storeH
public Producer(String producerName, StoreHouse storeHouse) {
this.producerName = producerN
this.storeHouse = storeH
public void setProducerName(String producerName) {
this.producerName = producerN
public String getProducerName() {
return producerN
public void run() {
execProcuct();
private void execProcuct() {
int i = 0;
while(true){
Product pro = new Product(i);
storeHouse.push(pro);
System.out.println(getProducerName() + " 生产了 " + pro);
Thread.sleep(2000);
} catch (InterruptedException e) {
package org.dennist.thread.
public class Consumer implements Runnable{
private String consumerName =
private StoreHouse storeHouse =
public Consumer(String consumerName, StoreHouse storeHouse) {
this.consumerName = consumerN
this.storeHouse = storeH
public void setConsumerName(String consumerName) {
this.consumerName = consumerN
public String getConsumerName() {
return consumerN
public void execConsume() {
while (true) {
System.out.println(getConsumerName() + " 消费了 " + storeHouse.pop());
Thread.sleep(5000);
} catch (InterruptedException e) {
public void run() {
execConsume();
package org.dennist.thread.
public class TestPC {
public static void main(String[] args) {
StoreHouse storeHouse = new StoreHouse();
Producer producer = new Producer("生产者", storeHouse);
Consumer comsumer = new Consumer("消费者", storeHouse);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(comsumer);
t1.start();
t2.start();
关于多线程同步
JAVA多线程同步主要依赖于若干方法和关键字
1&&wait方法:
&&&&&&&&该方法属于的方法,方法的作用是使得当前调用方法所在部分(代码块)的线程停止执行,并释放当前获得的调用所在的代码块的锁,并在其他线程调用或者方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
&&&&&&&&调用方法需要注意几点:
&&&&&&&&第一点:被调用的时候必须在拥有锁(即修饰的)的代码块中。
&&&&&&&&第二点:恢复执行后,从的下一条语句开始执行,因而方法总是应当在循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
&&&&&&&&第三点:若方法参数中带时间,则除了和被调用能激活处于状态(等待状态)的线程进入锁竞争外,在其他线程中它或者参数时间到了之后,该线程也将被激活到竞争状态。
&&&&&&&&第四点:方法被调用的线程必须获得之前执行到时释放掉的锁重新获得才能够恢复执行。
2&&notify方法和方法:
&&&&&&&&notify方法通知调用了方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待所释放的锁。
&&&&&&&&notifyAll方法则唤醒所有调用了方法,尚未激活的进程进入竞争队列。
3&synchronized关键字:
&&&&&&&&第一点:用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
&&&&&&&&第二点:用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
&&&&&&&&第三点:修饰一个代码块。类似这样:。表示一个线程要执行该代码块,必须获得的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的数组对象做非常经济。
4&atomic&action(原子操作):
&&&&&&&&在中,以下两点操作是原子操作。但是和中并不如此。
&&&&&&&&第一点:对引用变量和除了和之外的原始数据类型变量进行读写。
&&&&&&&&第二点:对所有声明为的变量(包括和)的读写。
&&&&&&&&另外:在和包中提供了一些不依赖于同步机制的线程安全的类和方法。
进程间通信
进程间通信(,),指至少两个进程或线程间传送数据或信号的一些技术或方法。线程是计算机系统分配资源的最小单位。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。这些进程可以运行在同一计算机上或网络连接的不同计算机上。
进程间通信技术包括消息传递、同步、共享内存和远程过程调用。是一种标准的通信机制。
主要的IPC方法有
&&&&)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
)命名管道(named&pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system&V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
)内存映射(mapped&memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System&V的变种都支持套接字。
转载请注明出处:[]
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读& & package test java . public class SellBuy { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Q q = new Q(); new Thread(new Producer(q)).start(); new Thread(new Comsumer(q)).start(); } }& & package testjava.& & public class SellBuy {& & /**& & * @param args& & */& & public static void main(String[] args) {& & // TODO Auto-generated method stub& & Q q = new Q();& & new Thread(new Producer(q)).start();& & new Thread(new Comsumer(q)).start();& & }& & }& & class Producer implements Runnable& & {& & Q& & public Producer(Q q)& & {& & this.q=q;& & }& & public void run()& & {& & int i=0;& & while(true)& & {& & if(i==0)& & q.put("zhangsan","male");& & else& & q.put("lisi","femail");& & i=(i+1)%2;& & }& & }& & }& & class Comsumer implements Runnable& & {& & Q& & public Comsumer(Q q)& & {& & this.q=q;& & }& & public void run()& & {& & while(true)& & {& & q.get();& & }& & }& & }& & class Q& & {& & String name="unknown";& & String sex="unkonwn";& & boolean bFull=& & public synchronized void put(String name,String sex)& & {& & if(bFull)& & try {wait();} catch (Exception e) {}& & this.name=& & try {Thread.sleep(1);} catch (Exception e) {}& & this.sex=& & bFull=& & notify();& & }& & public synchronized void get()& & {& & if(!bFull)& & try {wait();} catch (Exception e) {}& & System.out.println(name+":"+sex);& & bFull=& & notify();& & }& & }& & 原文转自:http://www.ltesting.net
声明:该文章系网友上传分享,此内容仅代表网友个人经验或观点,不代表本网站立场和观点;若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向
上一篇:下一篇:
相关经验教程
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.003 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益推荐这篇日记的豆列
······生产者消费者问题的Java实现_Linux编程_Linux公社-Linux系统门户网站
你好,游客
生产者消费者问题的Java实现
来源:Linux社区&
作者:longshengguoji
生产者和消费者是多线程经典的问题,生产者和消费者问题的核心是同步的问题,同步问题的核心是要保证同一个资源被多个线程并发访问时的完整性,常用的方法是采用信号或加锁机制,保证资源在任一时刻只能被一个线程访问。这一问题用java来实现的话主要有4种方式。1.wait()/notify();2.await()/signal(); 3.blockingQuene 4.PipedInputStream/pipedOutputStream
下面分别来实现。
1.利用wait()和notify()来实现Wait()方法:当缓冲区已空/满时,生产者/消费者停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行。
Notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
Java中介者设计模式
Java 设计模式之模板方法开发中应用
设计模式之 Java 中的单例模式(Singleton)
Java对象序列化
大话设计模式(带目录完整版) PDF+源代码
Java中的函数传递
下面看看代码实现:
首先定义商店类:
package ConsumerAndProducerP&import java.util.LinkedL&/**&* @author: zhuwei&* @ClassName: 商店类&* @Description: TODO&* @Date: 下午3:58:01&*/public class Storage{&& & //定义仓库最大容量100& & private final int MAX_SIZE = 100;& & private LinkedList&Object& list= new LinkedList&&();& & & //生产num个商品& & public void produce(int num) throws Exception& & {& & & synchronized(list)& & & {& & & & & //假如仓库容量不足& & & & & if(list.size()+num&MAX_SIZE)& & & & & {& & & & & & & System.out.println("仓储容量不足");& & & & & & & & & & & & & //线程等待& & & & & & & list.wait();& & & & & }& & & & & //仓库容量可以容量生产者的生产,则生产& & & & & for(int i = 0;i &i++)& & & & & {& & & & & & & list.add(new Object());& & & & & }& & & & & System.out.println("生产者生产产品数量为:"+ num);& & & & & list.notifyAll();& & & }& & }& & & //消费num个商品& & public void consume(int num) throws Exception& & {& & & synchronized(list)& & & {& & & & & //加入仓库中的商品不能满足消费者的需求,线程等待& & & & & if(list.size() & num)& & & & & {& & & & & & & System.out.println("仓库中的商品不能满足消费者需求");& & & & & & & list.wait();& & & & & }& & & & & for(int i = 0;i &i++)& & & & & {& & & & & & & list.remove();& & & & & }& & & & & System.out.println("消费者消费商品数量为:"+num);& & & & & list.notifyAll();& & & }& & }}
定义生产者类
package ConsumerAndProducerP&&/**&* @author: zhuwei&* @ClassName: 生产者线程&* @Description: TODO&* @Date: 下午3:57:15&*/public class Consumer implements Runnable{&& & //消费商品数量& && & & private S& & & & public void consume(int num)& & {& & & try& & & {& & & & & storage.consume(num);& & & } catch (Exception e)& & & {& & & & & // TODO Auto-generatedcatch block& & & & & e.printStackTrace();& & & }& & }& & & public int getNumber()& & {& & && & }&&&& & public void setNumber(int number)& & {& & & this.number =& & }&&&& & public Storage getStorage()& & {& & && & }&&&& & public void setStorage(Storage storage)& & {& & & this.storage =& & }&&&& & @Override& & public void run()& & {& & & // TODO Auto-generatedmethod stub& & & consume(number);& & }&}
定义消费者类:
package ConsumerAndProducerP&/**&* @author: zhuwei&* @ClassName: 消费者线程&* @Description: TODO&* @Date: 下午3:57:38&*/public class Producer implements Runnable{& & //生产的商品数量& && & & private S& & & public void produce(int num)& & {& & & try& & & {& & & & & storage.produce(num);& & & } catch (Exception e)& & & {& & & & & // TODO Auto-generatedcatch block& & & & & e.printStackTrace();& & & }& & }& & & public int getNumber()& & {& & && & }&& & public void setNumber(int number)& & {& & & this.number =& & }&& & public Storage getStorage()& & {& & && & }&& & public void setStorage(Storage storage)& & {& & & this.storage =& & }&& & @Override& & public void run()& & {& & & // TODO Auto-generatedmethod stub& & & produce(number);& & }&}
创建测试类:
package ConsumerAndProducerP&public class Test{&& & public static void main(String[] args)& & {& & & // TODO Auto-generatedmethod stub& & & //仓库对象& & & Storage storage = new Storage();& & & & & & //消费者对象& & & Consumer c1 = new Consumer();& & & c1.setNumber(10);& & & c1.setStorage(storage);& & & Consumer c2 = new Consumer();& & & c2.setNumber(80);& & & c2.setStorage(storage);& & & & & & //生产者对象& & & Producer p1 = new Producer();& & & p1.setNumber(20);& & & p1.setStorage(storage);& & & Producer p2 = new Producer();& & & p2.setNumber(50);& & & p2.setStorage(storage);& & & & & & p1.run();& & & c1.run();& & & p2.run();& & & c2.run();& & & & & }&}
更多详情见请继续阅读下一页的精彩内容:
相关资讯 & & &
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款您的位置: &
两种解决生产者—消费者问题的Java实现模型
优质期刊推荐

我要回帖

更多关于 java线程生产者消费者 的文章

 

随机推荐