用wait和notify/notifyAll实现生产者消费者模式

生产者消费者模式的实现方式有很多种,比如采用Condition条件变量或者利用阻塞队列来进行实现。本文将采用Object中自带的wait和notify/notifyAll方法来实现这个模式。实现代码如下:

import java.util.LinkedList;

public class ProducerConsumerPattern{

	public static final int MAX_CAPACITY = 5;      //缓冲区最大容量
	static LinkedList<Object> list = new LinkedList<Object>();   //用一个Linked作为缓冲区
	static class Producer implements Runnable {         //生产者
		public void run() {
			while(true) {                    //循环生产产品
				synchronized(list) {    //获取缓冲区的锁
					while(list.size()==MAX_CAPACITY) {   // 如果缓冲区已满,
						try {
							System.out.println("当前产品个数为" + list.size() + "已达到最大容量,等待消费者消费。。。");
							list.wait();                  //则调用wait进行阻塞,并释放缓冲区的锁
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					System.out.println("当前产品个数为" + list.size());
					list.add(new Object());               //缓冲区未满,则生产产品
					System.out.println("生产了一个产品,当前产品个数为" + list.size());
					list.notifyAll();             //生产完一个产品之后,通知所有阻塞在wait调用中的线程
				}
				try {
					Thread.sleep(1000);   //模拟花费一段时间进行生产
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	static class Consumer implements Runnable {    //消费者
		public void run() {
			while(true) {         //不断消费产品
				synchronized(list) {    //获取缓冲区的锁
					while(list.size()==0) {       //如果缓冲区为空,
						try {
							System.out.println("当前产品个数为" + list.size() + ",等待生产者生产。。。");
							list.wait();     //则进行阻塞,并释放缓冲区的锁
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					System.out.println("当前产品个数为" + list.size());
					list.remove();     //缓冲区不空,则消费一个产品
					System.out.println("消费了一个产品,当前产品个数为" + list.size());
					list.notifyAll();    //消费一个产品之后,通知所有阻塞在wait调用上的线程
				}
				try {
					Thread.sleep(2000);   //模拟花费一段时间进行消费
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		for(int i=0; i<3; i++) {     //创建3个生产者进行生产
			new Thread(new Producer()).start();
		}
		for(int i=0; i<5; i++) {    //创建5个消费者进行消费
			new Thread(new Consumer()).start();
		}
		
	}
}

某一次的运行结果如下:

当前产品个数为0
生产了一个产品,当前产品个数为1
当前产品个数为1
生产了一个产品,当前产品个数为2
当前产品个数为2
生产了一个产品,当前产品个数为3
当前产品个数为3
消费了一个产品,当前产品个数为2
当前产品个数为2
消费了一个产品,当前产品个数为1
当前产品个数为1
消费了一个产品,当前产品个数为0
当前产品个数为0,等待生产者生产。。。
当前产品个数为0,等待生产者生产。。。
当前产品个数为0
生产了一个产品,当前产品个数为1
………………(省略部分过程)
当前产品个数为3
生产了一个产品,当前产品个数为4
当前产品个数为4
生产了一个产品,当前产品个数为5
当前产品个数为5已达到最大容量,等待消费者消费。。。
当前产品个数为5
消费了一个产品,当前产品个数为4

总结:在实现这个模式的过程中也遇到了一些问题,通过解决遇到的这些问题使自己对java多线程的机制也有了更进一步的了解。有些东西以为自己会,其实并不真的会,还是要多实践。

水平有限,如有不当之处,还望指正!



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值