wait与notifyAll实现简单的生产者消费者模式

来源:互联网 发布:vb开发彩票软件教程 编辑:程序博客网 时间:2024/05/27 20:07

前面转载了一篇用BlockingQueue实现生产者消费者模式的文章。文中提到了另外一种实现方式,利用对象的wait以及notifyAll方法。

先贴上代码:

package com.demo.test;import java.util.ArrayList;import java.util.List;public class ProducerConsumer {public static void main(String[] args) {// 建立仓库MyStack stack = new MyStack();// 生产者Producer producer = new Producer(stack);// 消费者Consumer consumer = new Consumer(stack);// 开始生产new Thread(producer).start();// 开始消费new Thread(consumer).start();}/** * 产品类 *  * @author kk *  */private static class Product {private int id;public Product(int productId) {this.id = productId;}@Overridepublic String toString() {return "product" + id;}}/** * 生产者, 负责生产产品 *  * @author kk *  */private static class Producer implements Runnable {private String name = "生产者";private MyStack myStack;public Producer(MyStack stack) {this.myStack = stack;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {// System.out.println("生产" + i);// 生产产品Product product = new Product(i);// 入库myStack.push(product);// 休息下try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}}/** * 消费者,消费产品 *  * @author kk *  */private static class Consumer implements Runnable {private String name = "消费者";private MyStack myStack;public Consumer(MyStack stack) {this.myStack = stack;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {// System.out.println("消费" + i);// 产品出库Product product = myStack.pop();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}/** * 实现自己的仓库,用来存放产品 *  * @author kk *  */private static class MyStack {private List<Product> products = new ArrayList<Product>();// 存放产品/** * 从仓库中获取产品来消费 *  * @return */public synchronized Product pop() {// 如果仓库已经消费空了,那你就等着新品上市吧if (products.size() == 0) {System.out.println("仓库已经空了,等待生产...");try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();// 通知生产// 仓库没空,从仓库中拿出一个产品Product product = products.get(0);products.remove(product);System.out.println("产品出库:" + product);return product;}/** * 将生产者生产的产品入库 *  * @param producedProduct */public synchronized void push(Product producedProduct) {// 如果当前仓库已经满了if (products.size() >= 5) {System.out.println("仓库已经满啦,没地方放了,快停止生产吧,通知消费者来消费");try {this.wait();// 停止生产} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();// 通知消费// 仓库未满,既然生产了就入库吧products.add(producedProduct);System.out.println("\t产品入库:" + producedProduct);}}}


运行结果:

仓库已经空了,等待生产...产品入库:product0产品出库:product0产品入库:product1产品入库:product2产品出库:product1产品入库:product3产品入库:product4产品入库:product5产品出库:product2产品入库:product6产品入库:product7产品出库:product3产品入库:product8仓库已经满啦,没地方放了,快停止生产吧,通知消费者来消费产品出库:product4产品入库:product9产品出库:product5产品出库:product6产品出库:product7产品出库:product8产品出库:product9


Notes:

1,wait()必须在synchronized 函数或者代码块里面,wait会让synchronized函数或者代码块所在线程暂时的停止运行,释放锁,丧失控制权,该线程进入等待,

让其它的线程有机会获得控制权,在条件满足的情况下调用notifyAll()来唤醒正在wait的线程,等待获取cpu时间,获取到后,继续往下执行;

2,生产者Producer和消费者Consumer要共用仓库MyStack;

3,notifyAll()方法是唤醒其他正在等待的线程,并不让出自己的cpu时间,还是会继续运行;

4,仓库空了,消费者wait,通知生产者赶紧生产notifyAll。仓库满了,生产者wait,通知消费者赶紧消费notifyAll;




0 0
原创粉丝点击