1. 吐司BlockingQueue
考虑下面这个使用BlockingQueue的示例。有一台机器具有三个任务:一个制作吐司,一个给吐司抹黄油,另一个在抹过黄油的吐司上吐果酱。我们可以通过各个处理过程之间的BlockingQueue来运行这个吐司制作程序:
2. class :
package lime.thinkingInJava._021._005._004;import com.sun.corba.se.impl.oa.toa.TOA;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit;/** * @Author : Lime * @Description : * @Remark : */class Toast{ public enum Status{DRY,BUTTERED,JAMMED} private Status status = Status.DRY; private final int id; public Toast(int idn){id = idn;} public void butter(){ status = Status.BUTTERED; } public void jam(){ status = Status.JAMMED; } public Status getStatus(){ return status; } public int getId(){ return id; } public String toString(){ return "Toast " + id + " : " + status; }}class ToastQueue extends LinkedBlockingQueue{}class Toaster implements Runnable{ private ToastQueue toastQueue; private int count = 0; private Random rand = new Random(47); public Toaster(ToastQueue tq){ toastQueue = tq; } public void run(){ try{ while (!Thread.interrupted()){ TimeUnit.MILLISECONDS.sleep(100 + rand.nextInt(100)); //Make toast Toast t = new Toast(count++); System.out.println(t); //Insert into queue toastQueue.put(t); } } catch (InterruptedException e) { System.out.println("Toaster interrupted"); } System.out.println("Toaster off"); }}//Apply butter to toastclass Butterer implements Runnable{ private ToastQueue dryQueue ,butteredQueue; public Butterer(ToastQueue dry , ToastQueue buttered){ dryQueue = dry; butteredQueue = buttered; } public void run(){ try{ while (!Thread.interrupted()){ //Blocks until next piece of toast is available; Toast t = dryQueue.take(); t.butter(); System.out.println(t); butteredQueue.put(t); } } catch (InterruptedException e) { System.out.println("Butterer interrupted"); } System.out.println("Butterer off"); }}//Apply jam to buttered toast;class Jammer implements Runnable{ private ToastQueue butteredQueue,finishedQueue; public Jammer(ToastQueue buttered,ToastQueue finished){ butteredQueue = buttered; finishedQueue = finished; } public void run(){ try{ while (!Thread.interrupted()){ //Blocks until next piece of toast is available; Toast t = butteredQueue.take(); t.jam(); System.out.println(t); finishedQueue.put(t); } } catch (InterruptedException e) { System.out.println("Jammer interrupted"); } System.out.println("Jammer off"); }}//Consume the toast;class Eater implements Runnable{ private ToastQueue finishedQueue; private int counter = 0; public Eater(ToastQueue finished){ this.finishedQueue = finished; } public void run(){ try{ while (!Thread.interrupted()){ //Blocks until next piece of toast is available; Toast t = finishedQueue.take(); //Verify that the toast is coming in order; //and that all pieces are getting jammed; if(t.getId() != counter++ || t.getStatus() != Toast.Status.JAMMED){ System.out.println(">>>> Error : " + t); System.exit(1); }else{ System.out.println("Chomp ! " + t); } } } catch (InterruptedException e) { System.out.println("Eater interrupted"); } System.out.println("Eater off"); }}public class ToastOMatic { public static void main(String[] args) throws InterruptedException { ToastQueue dryQueue = new ToastQueue(), butteredQueue = new ToastQueue(), finishedQueue = new ToastQueue(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new Toaster(dryQueue)); exec.execute(new Butterer(dryQueue,butteredQueue)); exec.execute(new Jammer(butteredQueue,finishedQueue)); TimeUnit.SECONDS.sleep(5); exec.shutdownNow(); }}
3. Console :
Toast 0 : DRYToast 0 : BUTTEREDToast 0 : JAMMEDToast 1 : DRYToast 1 : BUTTEREDToast 1 : JAMMEDToast 2 : DRYToast 2 : BUTTEREDToast 2 : JAMMEDToast 3 : DRYToast 3 : BUTTEREDToast 3 : JAMMEDToast 4 : DRYToast 4 : BUTTEREDToast 4 : JAMMEDToast 5 : DRYToast 5 : BUTTEREDToast 5 : JAMMEDToast 6 : DRYToast 6 : BUTTEREDToast 6 : JAMMEDToast 7 : DRYToast 7 : BUTTEREDToast 7 : JAMMEDToast 8 : DRYToast 8 : BUTTEREDToast 8 : JAMMEDToast 9 : DRYToast 9 : BUTTEREDToast 9 : JAMMEDToast 10 : DRYToast 10 : BUTTEREDToast 10 : JAMMEDToast 11 : DRYToast 11 : BUTTEREDToast 11 : JAMMEDToast 12 : DRYToast 12 : BUTTEREDToast 12 : JAMMEDToast 13 : DRYToast 13 : BUTTEREDToast 13 : JAMMEDToast 14 : DRYToast 14 : BUTTEREDToast 14 : JAMMEDToast 15 : DRYToast 15 : BUTTEREDToast 15 : JAMMEDToast 16 : DRYToast 16 : BUTTEREDToast 16 : JAMMEDToast 17 : DRYToast 17 : BUTTEREDToast 17 : JAMMEDToast 18 : DRYToast 18 : BUTTEREDToast 18 : JAMMEDToast 19 : DRYToast 19 : BUTTEREDToast 19 : JAMMEDToast 20 : DRYToast 20 : BUTTEREDToast 20 : JAMMEDToast 21 : DRYToast 21 : BUTTEREDToast 21 : JAMMEDToast 22 : DRYToast 22 : BUTTEREDToast 22 : JAMMEDToast 23 : DRYToast 23 : BUTTEREDToast 23 : JAMMEDToast 24 : DRYToast 24 : BUTTEREDToast 24 : JAMMEDToast 25 : DRYToast 25 : BUTTEREDToast 25 : JAMMEDToast 26 : DRYToast 26 : BUTTEREDToast 26 : JAMMEDToast 27 : DRYToast 27 : BUTTEREDToast 27 : JAMMEDToast 28 : DRYToast 28 : BUTTEREDToast 28 : JAMMEDToast 29 : DRYToast 29 : BUTTEREDToast 29 : JAMMEDToast 30 : DRYToast 30 : BUTTEREDToast 30 : JAMMEDToast 31 : DRYToast 31 : BUTTEREDToast 31 : JAMMEDToast 32 : DRYToast 32 : BUTTEREDToast 32 : JAMMEDToast 33 : DRYToast 33 : BUTTEREDToast 33 : JAMMEDJammer interruptedJammer offButterer interruptedButterer offToaster interruptedToaster off
4. Toast是一个使用enum值的优秀示例。注意,这个示例中没有任何显式的同步(即使用Lock对象或synchronized关键字的同步),因为同步由队列(其内部是同步的)和系统的设计隐式地管理了 ------ 每片Toast在任何时刻都只由一个任务在操作。因为队列的阻塞,使得处理过程将被自动地挂起和恢复。你可以看到由BlockingQueue产生的简化十分明显。在使用显示的wait()和notifyAll()时存在的类和类之间的耦合被消除了,因为每个类都只和它的BlockingQueue通信。
5. 鸣谢
6. 啦啦啦