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
原创粉丝点击