并发(四)

这篇写一个关于BlockingQueue的小例子。

BlockingQueue是阻塞队列,那么什么时候发生阻塞呢?一是队列,入列时没有值进行入列,二是出列时,没有值出列,这样就会发生阻塞。

代码例子如下:

 1 class Toast {
 2 
 3     public enum Status {
 4         DRY, BUTTERD, JAMMED
 5     }
 6     
 7     private Status status = Status.DRY;
 8     private final int id;
 9     public Toast(int idn) {
10         id = idn;
11     }
12     public void butter() {
13         status = Status.BUTTERD;
14     }
15     public void jam() {
16         status = Status.JAMMED;
17     }
18     public Status getStatus() {
19         return status;
20     }
21     public int getId() {
22         return id;
23     }
24     public String toString(){
25         return "Toast " + id + ": " + status;
26     }
27 }
View Code
 1 import java.util.concurrent.LinkedBlockingDeque;
 2 
 3 class ToastQueue extends LinkedBlockingDeque<Toast>{
 4 
 5     /**
 6      * 
 7      */
 8     private static final long serialVersionUID = 1L;
 9     
10 
11 }
View Code
 1 import java.util.Random;
 2 import java.util.concurrent.TimeUnit;
 3 
 4 public class Toaster implements Runnable {
 5 
 6     private ToastQueue taostQueut;
 7     private int count = 0;
 8     private Random rand = new Random(47);
 9     public Toaster(ToastQueue tq){
10         taostQueut = tq;
11     }
12     @Override
13     public void run() {
14 
15         try {
16             while(!Thread.interrupted()){
17                 TimeUnit.MICROSECONDS.sleep(100 + rand.nextInt(500));
18                 Toast toast = new Toast(count++);
19                 System.out.println(toast);
20                 taostQueut.put(toast);
21             }
22         }catch (InterruptedException e) {
23             System.out.println("Toaster interrupted");
24         }
25         System.out.println("Toaster off");
26     }
27 }
View Code
 1 public class Jammer implements Runnable {
 2 
 3     private ToastQueue butteredQueue, finishedQueue;
 4     public Jammer(ToastQueue butteredQueue, ToastQueue finishedQueue){
 5         this.butteredQueue = butteredQueue;
 6         this.finishedQueue = finishedQueue;
 7     }
 8     @Override
 9     public void run() {
10 
11         try {
12             while(!Thread.interrupted()){
13                 Toast toast = butteredQueue.take();
14                 toast.jam();
15                 System.out.println(toast);
16                 finishedQueue.put(toast);
17             }
18         }catch (InterruptedException e) {
19             System.out.println("Butterer interrupted");
20         }
21         System.out.println("Butterer off");
22     }
23 }
View Code
 1 public class Eatter implements Runnable {
 2 
 3     private ToastQueue finishedQueue;
 4     private int counter = 0;
 5     public Eatter(ToastQueue tq){
 6         finishedQueue = tq;
 7     }
 8     @Override
 9     public void run() {
10 
11         try {
12             while(!Thread.interrupted()){
13                 Toast toast = finishedQueue.take();
14                 if (toast.getId() != counter++ || toast.getStatus() != Toast.Status.JAMMED) {
15                     System.out.println(">>>> Eooro: " + toast);
16                     System.exit(1);
17                 } else {
18                     System.out.println("chomp " + toast);
19                 }
20             }
21         }catch (InterruptedException e) {
22             System.out.println("Eater interrupted");
23         }
24         System.out.println("Eater off");
25     }
26 }
View Code
 1 import java.util.concurrent.ExecutorService;
 2 import java.util.concurrent.Executors;
 3 import java.util.concurrent.TimeUnit;
 4 
 5 public class ToastOMatic {
 6 
 7     public static void main(String[] args) throws InterruptedException {
 8 
 9         ToastQueue dryQueue = new ToastQueue();
10         ToastQueue butteredQueue = new ToastQueue();
11         ToastQueue finishedQueue = new ToastQueue();
12         ExecutorService servie = Executors.newCachedThreadPool();
13         servie.execute(new Toaster(dryQueue));
14         servie.execute(new Butter(dryQueue, butteredQueue));
15         servie.execute(new Jammer(butteredQueue, finishedQueue));
16         servie.execute(new Eatter(finishedQueue));
17         TimeUnit.SECONDS.sleep(5);
18         servie.shutdownNow();
19     }
20 
21 }
View Code

上面组成了一个关于蛋糕摸黄油的小例子,很简单。一条生产线的专门生产蛋糕,另一条生产线是,生产后的蛋糕上抹上黄油,最后摸完黄油的蛋糕,作为成品,可以被吃掉了!

代码中没有显式的使用锁,但是全都在队列的内部进行实现,十分的方便。

今天在使用了alibaba开发规范插件后,发现创建线程池的方法不佳,在此进行记录。以后注意。

ExecutorService servie = Executors.newCachedThreadPool();     原先是这样创建的。检查后报出如下提示信息

"线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。"

因此,改为如下形式:

 

        ExecutorService servie = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(),
                // user-defined ThreadFactory
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName(r.getClass().getName());
                        return thread;
                    }
                },
                // user-defined Thread rejection policy
                new ThreadPoolExecutor.AbortPolicy());

自己以后创建线程池的时候会多多注意。

 

posted @ 2017-10-23 13:15  Mr.袋鼠  阅读(156)  评论(0编辑  收藏  举报