文档章节

java多线程之消费者生产者模式

明舞
 明舞
发布于 2014/11/04 10:23
字数 809
阅读 52
收藏 0
/*@author shijin
* 生产者与消费者模型中,要保证以下几点:
* 1 同一时间内只能有一个生产者生产		生产方法加锁sychronized
* 2 同一时间内只能有一个消费者消费		消费方法加锁sychronized
* 3 生产者生产的同时消费者不能消费		生产方法加锁sychronized
* 4 消费者消费的同时生产者不能生产		消费方法加锁sychronized
* 5 共享空间空时消费者不能继续消费		消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行
* 6 共享空间满时生产者不能继续生产		生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行   
*/

//主类
class  ProducerConsumer
{
	public static void main(String[] args) 
	{
		StackBasket s = new StackBasket();
		Producer p = new Producer(s);
		Consumer c = new Consumer(s);
		Thread tp = new Thread(p);
		Thread tc = new Thread(c);
		tp.start();
		tc.start();
	}
}

//
class Mantou
{
	private int id;
	
	Mantou(int id){
		this.id = id;
	}

	public String toString(){
		return "Mantou :" + id;
	}
}

//共享栈空间
class StackBasket
{
	Mantou sm[] = new Mantou[6];
	int index = 0;
	
	/** 
	* show 生产方法.
	* show 该方法为同步方法,持有方法锁;
	* show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费;
	* show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态,
	* show 等生产结束释放同步方法锁后消费才能持有该锁进行消费
	* @param m 元素
	* @return 没有返回值 
	*/ 

	public synchronized void push(Mantou m){
		try{
			while(index == sm.length){
				System.out.println("!!!!!!!!!生产满了!!!!!!!!!");
				this.wait();
			}
			this.notify();
		}catch(InterruptedException e){
			e.printStackTrace();
		}catch(IllegalMonitorStateException e){
			e.printStackTrace();
		}
		
		sm[index] = m;
		index++;
		System.out.println("生产了:" + m + " 共" + index + "个馒头");
	}

	/** 
	* show 消费方法
	* show 该方法为同步方法,持有方法锁
	* show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产;
	* show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态
	* show 等消费结束释放同步方法锁后生产才能持有该锁进行生产
	* @param b true 表示显示,false 表示隐藏 
	* @return 没有返回值 
	*/ 
	public synchronized Mantou pop(){
		try{
			while(index == 0){
				System.out.println("!!!!!!!!!消费光了!!!!!!!!!");
				this.wait();
			}
			this.notify();
		}catch(InterruptedException e){
			e.printStackTrace();
		}catch(IllegalMonitorStateException e){
			e.printStackTrace();
		}
		index--;
		System.out.println("消费了:---------" + sm[index] + " 共" + index + "个馒头");
		return sm[index];
	}
}

class Producer implements Runnable
{
	StackBasket ss = new StackBasket();
	Producer(StackBasket ss){
		this.ss = ss;
	}

	/** 
	* show 生产进程. 
	*/ 
	public void run(){
		for(int i = 0;i < 20;i++){
			Mantou m = new Mantou(i);
			ss.push(m);
//			System.out.println("生产了:" + m + " 共" + ss.index + "个馒头");
//			在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱
			try{
				Thread.sleep((int)(Math.random()*500));
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}

class Consumer implements Runnable
{
	StackBasket ss = new StackBasket();
	Consumer(StackBasket ss){
		this.ss = ss;
	}

	/** 
	* show 消费进程.
	*/ 
	public void run(){
		for(int i = 0;i < 20;i++){
			Mantou m = ss.pop();
//			System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头");
//	同上	在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱
			try{
				Thread.sleep((int)(Math.random()*1000));
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}

© 著作权归作者所有

明舞
粉丝 231
博文 424
码字总数 516555
作品 0
程序员
私信 提问
Java多线程生产者消费者实例

Java生产者消费者实例 设计:涉及到的类有食物、厨师、服务员、顾客以及测试类。厨师负责生产食物,服务员服务于顾客,顾客负责点餐以及吃饭。 技术点:Java多线程,线程安全(synchronized),...

cicadaT
2017/11/05
863
1
零基础学Java10系列三:Java高级编程​​​​​​​

更多关于Java高级编程内容链接:零基础学Java10系列三:Java高级编程——阿里云大学 多线程: 生产者和消费者指的是两个不同的线程类对象,两个进程公用一个公共的固定大小缓冲区。其中之一的...

阿里云大学云百科
04/26
36
0
Java多线程20 Worker Thread模式

Java多线程目录 1.Worker Thread模式 Worker的意思是工作的人,在Worker Thread模式中,工人线程Worker thread会逐个取回工作并进行处理,当所有工作全部完成后,工人线程会等待新的工作到来...

香沙小熊
02/13
0
0
聊聊并发(十)生产者消费者模式

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。 在线程世界里,生产者就是生产数据的线程,消...

陶邦仁
2015/03/23
447
0
SpringBoot 整合 kafka 实现组订阅模式

SpringBoot 整合 kafka 实现组订阅模式: 工程结构图 消息生产者pom.xml配置 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" </project> 消息消......

泉天下
2018/10/18
698
0

没有更多内容

加载失败,请刷新页面

加载更多

链表中环的入口节点

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 思路: public ListNode EntryNodeOfLoop(ListNode pHead) { if (pHead == null || pHead.next == null) ...

Garphy
29分钟前
4
0
Spring5 源码分析-容器刷新-invokeBeanFactoryPostProcessors()方法

上一篇:Spring5 源码分析-容器刷新-prepareBeanFactory()方法 该方法主要完成以下功能: 1.实例化ConfigurationClassPostProcessor,并调用ConfigurationClassPostProcessor.postProcessBe...

特拉仔
29分钟前
5
0
为什么MySQL用B+树做索引

索引这个词,相信大多数人已经相当熟悉了,很多人都知道MySQL的索引主要以B+树为主,但是要问到为什么用B+树,恐怕很少有人能把前因后果讲述的很完整。本文就来从头到尾介绍下数据库的索引。...

小致Daddy
54分钟前
7
0
网站前台的三级联动数据封装

我在进行项目时候遇到了一个进行数据封装的一个功能,进行数据的封装的功能也挺复杂,来回试了好几十种方法.最后使用的是这种方法. 使用一个pojo进行封装两个数据,一个是list一个是实体类. 具体...

小天丶羽
57分钟前
4
0
创龙基于TI AM437x ARM Cortex-A9 + Xilinx Spartan-6 FPGA的SPI FLASH、硬件加密芯片

TL437xF-EVM是一款广州创龙基于TI AM437x ARM Cortex-A9 + Xilinx Spartan-6 FPGA设计的开发板,底板采用沉金无铅工艺的4层板设计,尺寸为240mm*130mm,它为用户提供了SOM-TL437xF核心板的测...

Tronlong创龙
59分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部