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

/*@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();
			}
		}
	}
}
  • 12
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
多线程生产者消费者模式是一种常见的并发编程模式,用于解决生产者消费者之间的数据交互问题。在Java中,可以使用多线程和相关的同步机制来实现生产者消费者模式。 在这种模式中,生产者负责生成数据,并将数据放入共享的缓冲区中,而消费者则从缓冲区中取出数据进行处理。为了保证线程安全和避免竞态条件,需要使用锁或其他同步机制来控制对共享缓冲区的访问。 以下是一个简单的Java多线程生产者消费者的示例代码: ```java import java.util.LinkedList; class ProducerConsumer { private LinkedList<Integer> buffer = new LinkedList<>(); private int capacity = 10; public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { while (buffer.size() == capacity) { wait(); } System.out.println("Producer produced: " + value); buffer.add(value++); notify(); Thread.sleep(1000); } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { while (buffer.isEmpty()) { wait(); } int value = buffer.removeFirst(); System.out.println("Consumer consumed: " + value); notify(); Thread.sleep(1000); } } } } public class Main { public static void main(String[] args) { ProducerConsumer pc = new ProducerConsumer(); Thread producerThread = new Thread(() -> { try { pc.produce(); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread consumerThread = new Thread(() -> { try { pc.consume(); } catch (InterruptedException e) { e.printStackTrace(); } }); producerThread.start(); consumerThread.start(); } } ``` 上述代码中,ProducerConsumer类维护了一个缓冲区buffer和一个容量capacity。生产者通过调用produce方法向缓冲区中添加数据,消费者通过调用consume方法从缓冲区中取出数据。在生产者消费者的方法中,使用synchronized关键字来保证同一时间只有一个线程能够访问共享资源,并使用wait和notify方法来实现线程间的通信。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值