用Condition条件变量实现生产者消费者模式
2016-04-01 17:40
477 查看
import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ProducerConsumerPattern{ public static final int MAX_CAP = 20; static LinkedList<Object> list = new LinkedList<Object>(); static ReentrantLock lock = new ReentrantLock(); static Condition notFull = lock.newCondition(); static Condition notEmpty = lock.newCondition(); static class Producer implements Runnable { @Override public void run() { while(true) { try { lock.lock(); while(list.size() == MAX_CAP) { try { System.out.println("当前已有"+list.size()+"个产品,缓冲区已满,请等待消费者消费"); notFull.await(); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } list.add(new Object()); System.out.println("生产了一个产品,当前产品个数为 " + list.size()); notEmpty.signalAll(); } finally { lock.unlock(); } Thread.yield(); } } } static class Consumer implements Runnable { @Override public void run() { while(true) { try { lock.lock(); while(list.size() == 0) { try { System.out.println("当前已有"+list.size()+"个产品,缓冲区已空,请等待生产者生产"); notEmpty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } list.remove(); try { Thread.sleep(700); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("消费了一个产品,当前产品个数为 " + list.size()); notFull.signalAll(); } finally { lock.unlock(); } Thread.yield(); } } } public static void main(String[] args) throws InterruptedException { 4000 for(int i=0; i<3; i++) { new Thread(new Producer()).start(); } for(int i=0; i<3; i++) { new Thread(new Consumer()).start(); } } }
部分输出结果如下:
生产了一个产品,当前产品个数为 11
生产了一个产品,当前产品个数为 12
生产了一个产品,当前产品个数为 13
消费了一个产品,当前产品个数为 12
消费了一个产品,当前产品个数为 11
消费了一个产品,当前产品个数为 10
消费了一个产品,当前产品个数为 9
…………………………(省略部分输出)
生产了一个产品,当前产品个数为 16
生产了一个产品,当前产品个数为 17
生产了一个产品,当前产品个数为 18
生产了一个产品,当前产品个数为 19
消费了一个产品,当前产品个数为 18
生产了一个产品,当前产品个数为 19
生产了一个产品,当前产品个数为 20
当前已有20个产品,缓冲区已满,请等待消费者消费
当前已有20个产品,缓冲区已满,请等待消费者消费
消费了一个产品,当前产品个数为 19
消费了一个产品,当前产品个数为 18
消费了一个产品,当前产品个数为 17
总结:用条件变量与用wait和notify/notifyAll实现这个模式有一个不同之处在于,Condition的signalAll方法只能唤醒在某一条件上进行阻塞的线程,比如notEmpty.signalAll()只能唤醒通过notEmpty.await()方法而阻塞的线程,在这个例子中的话也就是说生产者调用notEmpty.signalAll()只能唤醒消费者线程,而notifyAll()会唤醒所有在同一个对象锁(Object monitor)上进行等待的线程,比如说生产者和消费者都会因争夺缓冲区对象的锁而导致阻塞,同时在缓冲区满时生产者会调用wait方法进行阻塞,在缓冲区空时消费者会调用wait方法进行阻塞,一旦有线程(不管是生产者还是消费者)调用了notifyAll()方法,则所有的阻塞在同一个Object
monitor上的线程都会被唤醒。也就是说Condition的signalAll()是基于某个条件变量进行唤醒,notifyAll是基于某个对象锁(Object monitor)进行唤醒。
以上总结纯属个人的体会,可能有误。关于这两种实现方式的详细差别,以后再作深入学习。水平有限,如有不当之处,还望指正!
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树