J.U.C--集合--生产者与消费者队列BlockingQueue
来源:互联网 发布:js 将a标签隐藏 编辑:程序博客网 时间:2024/06/16 10:24
生产者与消费者队列
通过wait()和notifyAll()可以解决人物之间互操作的问题,但是这是一种比较低级的方式,每次交互都必须握手,过程十分复杂。更好的方法是我们使用同步队列来解决任务之间相互协作的问题。
同步队列在任何时刻都只允许一个任务插入或则删除元素,并且在队列为空时任务自动阻塞。java.util.concurrent.BlockingQueue接口提供了这个队列,并给出了几个标准实现。一般我们可以使用LinkedBlockingQueue,这是一个无界队列,底层用链表实现。或则是ArrayBlockingQueue,它具有固定的尺寸,因此在阻塞之前可以放置有限数量的元素。
java.util.concurrent包中实现的各种阻塞队列都包含了足够的内部同步机制,从而安全的将对象从生产者线程发布到消费者线程
下面是一个典型的生产者和消费者队列的案例:
package thread;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.*;import java.util.*;import static thread.Print.*;/*** * BlockingQueue例子:一台机器有三个任务, * A制作吐司,B给吐司抹黄油,C给吐司末果酱, * 制作的顺序必须是A-》B-》C * 阻塞队列里面保存的应该是吐司对象 */class Toast { /** * 枚举表示吐司制作的几个过程 */ public enum Status { DRY, BUTTERED, JAMMED } //设置初试状态 private Status status = Status.DRY; //设置每个吐司的唯一id private final int id; public Toast(int idn) { this.id = idn; } //涂黄油 public void butter() { this.status = Status.BUTTERED; } //涂果酱 public void jam() { status = Status.JAMMED; } //获取当前吐司的状态 public Status getStatus() { return status; } //获取当前吐司的id public int getId() { return id; } public String toString() { return "Toast " + id + ": " + status; }}/** * 吐司的阻塞队列,队列里面的元素对象就是吐司对象,三个任务之间维护的就是吐司 */class ToastQueue extends LinkedBlockingQueue<Toast> {}/** * 制作吐司的线程 * 这个线程只需要与已做好的吐司队列这一个队列交互 * 将做好的吐司存放在吐司队列中, * 通过构造器传入队列 */class Toaster implements Runnable { private ToastQueue toastQueue;//构造器将会传入的阻塞队列对象 private int count = 0;// private Random rand = new Random(47); public Toaster(ToastQueue tq) { this.toastQueue = tq; } @Override public void run() { try { while(!Thread.interrupted()) { //制作吐司的时间消耗 //TimeUnit.MILLISECONDS.sleep(100 + rand.nextInt(100)); TimeUnit.MILLISECONDS.sleep(2); //创建吐司对象 Toast t = new Toast(count++); print(t); //将新建的吐司放在队列中 toastQueue.put(t); } } catch(InterruptedException e) { print("Toaster interrupted"); } print("Toaster off"); }}/** * 给吐司抹黄油的线程 * 这个任务设计到两个队列,首先从吐司队列中能取出吐司,然后再抹黄油。 */class Butterer implements Runnable { private ToastQueue dryQueue, butteredQueue; public Butterer(ToastQueue dry, ToastQueue buttered) { this.dryQueue = dry; this.butteredQueue = buttered; } public void run() { try { while(!Thread.interrupted()) { //阻塞等待吐司队列中有可以抹黄油的吐司对象 Toast t = dryQueue.take(); //抹黄油 500ms TimeUnit.MILLISECONDS.sleep(10); t.butter(); print(t); butteredQueue.put(t); } } catch(InterruptedException e) { print("Butterer interrupted"); } print("Butterer off"); }}//给吐司抹上果酱的线程//这个任务设计到两个队列,首先从黄油队列中取出,然后抹果酱,加入果酱队列(也就是成品了)。class Jammer implements Runnable { private ToastQueue butteredQueue, finishedQueue; public Jammer(ToastQueue buttered, ToastQueue finished) { this.butteredQueue = buttered; this.finishedQueue = finished; } public void run() { try { while(!Thread.interrupted()) { // Blocks until next piece of toast is available: Toast t = butteredQueue.take(); //抹果酱 500ms TimeUnit.MILLISECONDS.sleep(10); t.jam(); print(t); finishedQueue.put(t); } } catch(InterruptedException e) { print("Jammer interrupted"); } print("Jammer off"); }}//最后的吃吐司的线程,字设计到class Eater implements Runnable { private ToastQueue finishedQueue,eatedQueue; private int counter = 0; public Eater(ToastQueue finished, ToastQueue eated) { finishedQueue = finished; this.eatedQueue = eated; } public void run() { try { while(!Thread.interrupted()) { // Blocks until next piece of toast is available: Toast t = finishedQueue.take(); TimeUnit.MILLISECONDS.sleep(100);//吃 eatedQueue.put(t);//装入吃完了的队列 // Verify that the toast is coming in order, // and that all pieces are getting jammed: if(t.getId() != counter++ || t.getStatus() != Toast.Status.JAMMED) { print(">>>> Error: " + t); System.exit(1); } else print("Chomp! " + t); } } catch(InterruptedException e) { print("Eater interrupted"); } print("Eater off"); }}/** * 最后的main主线程 */public class ToastOMatic { public static void main(String[] args) throws Exception { //这里定义了三个阻塞队列 //A是制作吐司的队列 //B是抹黄油的队列 //C是摸果酱的队列 ToastQueue dryQueue = new ToastQueue(); ToastQueue butteredQueue = new ToastQueue(); ToastQueue finishedQueue = new ToastQueue(); ToastQueue eatedQueue = new ToastQueue(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new Toaster(dryQueue)); exec.execute(new Toaster(dryQueue)); exec.execute(new Toaster(dryQueue));//三个人做吐司 exec.execute(new Butterer(dryQueue, butteredQueue)); exec.execute(new Jammer(butteredQueue, finishedQueue)); //三个人吃 exec.execute(new Eater(finishedQueue,eatedQueue)); exec.execute(new Eater(finishedQueue,eatedQueue)); exec.execute(new Eater(finishedQueue,eatedQueue)); TimeUnit.SECONDS.sleep(10); exec.shutdownNow(); //最后统计三个队列中的信息 print("============================================="); print(dryQueue.size()); print(butteredQueue.size()); print(finishedQueue.size()); print(eatedQueue.size()); }}/*Toast 0: DRYToast 0: DRYToast 0: DRYToast 1: DRYToast 1: DRYToast 1: DRYToast 2: DRYToast 2: DRYToast 2: DRYToast 3: DRY..............................Jammer interruptedToaster interruptedEater interruptedEater offToaster interruptedToaster offToaster offJammer offEater interruptedToaster interruptedToaster offEater offButterer interruptedButterer offEater interruptedEater off=============================================127331675297/
最后附上github坐标
完整源码:
1 0
- J.U.C--集合--生产者与消费者队列BlockingQueue
- BlockingQueue阻塞队列和生产者-消费者模式
- 使用阻塞队列BlockingQueue实现生产者消费者
- 经典的生产者与消费者模型(基于BlockingQueue队列实现)
- 【死磕Java并发】-----J.U.C之阻塞队列:BlockingQueue总结
- 生产者-消费者-BlockingQueue
- BlockingQueue 生产者-消费者
- BlockingQueue生产者消费者
- c 生产者与消费者
- 生产者和消费者之BlockingQueue(阻塞队列)详解
- 用阻塞队列(BlockingQueue)实现读写(生产者消费者)线程
- JAVA生产者与消费者模式 BlockingQueue与ExecutorService实例
- 使用BlockingQueue来简化消费者与生产者的问题
- 使用BlockingQueue来简化消费者与生产者的问题
- 生产者,消费者的BlockingQueue实现
- 生产者-消费者 BlockingQueue 运用示例
- 有限容量BlockingQueue:消费者生产者
- 有限容量BlockingQueue:消费者生产者
- Java并发之终结任务
- HDU 1053 Entropy 模拟哈夫曼树
- 设计模式之简单工厂模式
- 《Java并发编程实战》读书笔记五:深入理解同步实现
- Java并发之线程之间协作
- J.U.C--集合--生产者与消费者队列BlockingQueue
- 数据操作语言
- 第一周课后题
- QA的一生
- Linux命令1:压缩和解压
- Linux系统编程:标准IO操作--索引对应路径下的文件
- mac 下Atom 隐藏.DS_Store
- Unity平台的预处理
- Apache Shiro学习