国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java多線程學習-java.util.concurrent詳解(四) BlockingQueue

2019-11-11 06:44:19
字體:
來源:轉載
供稿:網友

java多線程學習-java.util.concurrent詳解(四) BlockingQueue

7.BlockingQueue     “支持兩個附加操作的 Queue,這兩個操作是:獲取元素時等待隊列變為非空,以及存儲元素時等待空間變得可用。“     這里我們主要討論BlockingQueue的最典型實現:LinkedBlockingQueue 和ArrayBlockingQueue。兩者的不同是底層的數據結構不夠,一個是鏈表,另外一個是數組。         后面將要單獨解釋其他類型的BlockingQueue和SynchronousQueue     BlockingQueue的經典用途是 生產者-消費者模式     代碼如下: 
import java.util.Random;  import java.util.concurrent.BlockingQueue;  import java.util.concurrent.LinkedBlockingQueue;    public class TestBlockingQueue {        public static void main(String[] args) {          final BlockingQueue<Integer> queue=new LinkedBlockingQueue<Integer>(3);          final Random random=new Random();                    class PRoducer implements Runnable{              @Override              public void run() {                  while(true){                      try {                          int i=random.nextInt(100);                          queue.put(i);//當隊列達到容量時候,會自動阻塞的                          if(queue.size()==3)                          {                              System.out.println("full");                          }                      } catch (InterruptedException e) {                          e.printStackTrace();                      }                  }              }          }                    class Consumer implements Runnable{              @Override              public void run() {                  while(true){                      try {                          queue.take();//當隊列為空時,也會自動阻塞                          Thread.sleep(1000);                      } catch (InterruptedException e) {                          e.printStackTrace();                      }                  }              }          }                    new Thread(new Producer()).start();          new Thread(new Consumer()).start();      }    }  總結:BlockingQueue使用時候特別注意take 和 put 8. DelayQueue 我們先來學習一下JDK1.5 API中關于這個類的詳細介紹:     “它是包含Delayed 元素的一個無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部 是延遲期滿后保存時間最長的 Delayed 元素。如果延遲都還沒有期滿,則隊列沒有頭部,并且 poll 將返回 null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小于等于 0 的值時,將發生到期。即使無法使用 take 或 poll 移除未到期的元素,也不會將這些元素作為正常元素對待。例如,size 方法同時返回到期和未到期元素的計數。此隊列不允許使用 null 元素。”     在現實生活中,很多DelayQueue的例子。就拿上海的SB會來說明,很多國家地區的開館時間不同。你很早就來到園區,然后急急忙忙地跑到一些心儀的館區,發現有些還沒開,你吃了閉門羹。     仔細研究DelayQueue,你會發現它其實就是一個PriorityQueue的封裝(按照delay時間排序),里面的元素都實現了Delayed接口,相關操作需要判斷延時時間是否到了。     在實際應用中,有人拿它來管理跟實際相關的緩存、session等    下面我就通過 “上海SB會的例子來闡述DelayQueue的用法” 代碼如下: 
import java.util.Random;  import java.util.concurrent.DelayQueue;  import java.util.concurrent.Delayed;  import java.util.concurrent.TimeUnit;    public class TestDelayQueue {        private class Stadium implements Delayed      {          long trigger;                    public Stadium(long i){              trigger=System.currentTimeMillis()+i;          }                    @Override          public long getDelay(TimeUnit arg0) {              long n=trigger-System.currentTimeMillis();              return n;          }            @Override          public int compareTo(Delayed arg0) {              return (int)(this.getDelay(TimeUnit.MILLISECONDS)-arg0.getDelay(TimeUnit.MILLISECONDS));          }                    public long getTriggerTime(){              return trigger;          }                }      public static void main(String[] args)throws Exception {          Random random=new Random();          DelayQueue<Stadium> queue=new DelayQueue<Stadium>();          TestDelayQueue t=new TestDelayQueue();                    for(int i=0;i<5;i++){              queue.add(t.new Stadium(random.nextInt(30000)));          }          Thread.sleep(2000);                    while(true){              Stadium s=queue.take();//延時時間未到就一直等待              if(s!=null){                  System.out.println(System.currentTimeMillis()-s.getTriggerTime());//基本上是等于0              }              if(queue.size()==0)                  break;          }      }  }   總結:適用于需要延時操作的隊列管理9. SynchronousQueue  我們先來學習一下JDK1.5 API中關于這個類的詳細介紹:     “一種阻塞隊列,其中每個插入操作必須等待另一個線程的對應移除操作 ,反之亦然。同步隊列沒有任何內部容量,甚至連一個隊列的容量都沒有。不能在同步隊列上進行 peek,因為僅在試圖要移除元素時,該元素才存在;除非另一個線程試圖移除某個元素,否則也不能(使用任何方法)插入元素;也不能迭代隊列,因為其中沒有元素可用于迭代。隊列的頭 是嘗試添加到隊列中的首個已排隊插入線程的元素;如果沒有這樣的已排隊線程,則沒有可用于移除的元素并且 poll() 將會返回 null。對于其他 Collection 方法(例如 contains),SynchronousQueue 作為一個空 collection。此隊列不允許 null 元素。     同步隊列類似于 CSP 和 Ada 中使用的 rendezvous 信道。它非常適合于傳遞性設計,在這種設計中,在一個線程中運行的對象要將某些信息、事件或任務傳遞給在另一個線程中運行的對象,它就必須與該對象同步。 “     看起來很有意思吧。隊列竟然是沒有內部容量的。這個隊列其實是BlockingQueue的一種實現。每個插入操作必須等待另一個線程的對應移除操作,反之亦然。它給我們提供了在線程之間交換單一元素的極輕量級方法    應用舉例:我們要在多個線程中傳遞一個變量。    代碼如下(其實就是生產者消費者模式) 
import java.util.Arrays;  import java.util.List;  import java.util.concurrent.BlockingQueue;  import java.util.concurrent.SynchronousQueue;    public class TestSynchronousQueue {        class Producer implements Runnable {          private BlockingQueue<String> queue;          List<String> objects = Arrays.asList("one", "two", "three");            public Producer(BlockingQueue<String> q) {              this.queue = q;          }            @Override          public void run() {              try {                  for (String s : objects) {                      queue.put(s);// 產生數據放入隊列中                      System.out.printf("put:%s%n",s);                  }                  queue.put("Done");// 已完成的標志              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }        class Consumer implements Runnable {          private BlockingQueue<String> queue;            public Consumer(BlockingQueue<String> q) {              this.queue = q;          }            @Override          public void run() {              String obj = null;              try {                  while (!((obj = queue.take()).equals("Done"))) {                      System.out.println(obj);//從隊列中讀取對象                      Thread.sleep(3000);     //故意sleep,證明Producer是put不進去的                  }              } catch (InterruptedException e) {                  e.printStackTrace();              }          }      }        public static void main(String[] args) {          BlockingQueue<String> q=new SynchronousQueue<String>();          TestSynchronousQueue t=new TestSynchronousQueue();          new Thread(t.new Producer(q)).start();          new Thread(t.new Consumer(q)).start();      }    }  總結:SynchronousQueue主要用于單個元素在多線程之間的傳遞 
上一篇:Java基礎語法

下一篇:Java位操作符

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 渝中区| 宁蒗| 焉耆| 通州区| 平原县| 余姚市| 紫阳县| 临潭县| 博湖县| 开原市| 瑞金市| 义马市| 永平县| 台南县| 卓尼县| 乐陵市| 防城港市| 商丘市| 溧水县| 瓮安县| 太湖县| 太仓市| 南城县| 凤山市| 运城市| 舞钢市| 株洲市| 鄂托克旗| 库伦旗| 华坪县| 贵德县| 拜泉县| 洛扎县| 万年县| 临城县| 甘泉县| 梅河口市| 武乡县| 喀喇沁旗| 策勒县| 台北市|