Cyh的博客

          Email:kissyan4916@163.com
          posts - 26, comments - 19, trackbacks - 0, articles - 220

          線程--BlockingQueue

          Posted on 2009-12-24 21:59 啥都寫點(diǎn) 閱讀(1037) 評(píng)論(0)  編輯  收藏 所屬分類: J2SE
                 本例介紹一個(gè)特殊的隊(duì)列:BlockingQueue,如果BlockingQueue是空的,從BlockingQueue取東西的操作將會(huì)被阻斷進(jìn)入等待狀態(tài),直到BlockingQueue進(jìn)了東西才會(huì)被喚醒,同樣,如果BlockingQueue是滿的,任何試圖往里存東西的操作也會(huì)被阻斷進(jìn)入等待狀態(tài),直到BlockingQueue里有空間時(shí)才會(huì)被喚醒繼續(xù)操作。
                 本例再次實(shí)現(xiàn)前面介紹的籃子程序,不過這個(gè)籃子中最多能放得蘋果數(shù)不是1,可以隨意指定。當(dāng)籃子滿時(shí),生產(chǎn)者進(jìn)入等待狀態(tài),當(dāng)籃子空時(shí),消費(fèi)者等待。

                 BlockingQueue定義的常用方法如下:
                          add(anObject):把a(bǔ)nObject加到BlockingQueue里,如果BlockingQueue可以容納,則返回true,否則拋出異常。
                          offer(anObject):表示如果可能的話,將anObject加到BlockingQueue里,即如果BlockingQueue可以容納,則返回true,否則返回false。
                          put(anObject):把a(bǔ)nObject加到BlockingQueue里,如果BlockingQueue沒有空間,則調(diào)用此方法的線程被阻斷直到BlockingQueue里有空間再繼續(xù)。
                          poll(time):取走BlockingQueue里排在首位的對(duì)象,若不能立即取出,則可以等time參數(shù)規(guī)定的時(shí)間,取不到時(shí)返回null。
                          take():取走BlockingQueue里排在首位的對(duì)象,若BlockingQueue為空,阻斷進(jìn)入等待狀態(tài)直到BlockingQueue有新的對(duì)象被加入為止。

                 BlockingQueue有四個(gè)具體的實(shí)現(xiàn)類,根據(jù)不同需求,選擇不同的實(shí)現(xiàn)類:
                          ArrayBlockingQueue:規(guī)定大小的BlockingQueue,其構(gòu)造函數(shù)必須帶一個(gè)int參數(shù)來指明其大小。其所含的對(duì)象是以FIFO(先入先出)順序排序的。
                          LinkedBlockingQueue:大小不定的BlockingQueue,若其構(gòu)造函數(shù)帶一個(gè)規(guī)定大小的參數(shù),生成的BlockingQueue有大小限制,若不帶大小參數(shù),所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定。其所含的對(duì)象是以FIFO順序排序的。
                          PriorityBlockingQueue:類似于LinkedBlockingQueue,但其所含對(duì)象的排序不是FIFO,而是依據(jù)對(duì)象的自然排序順序或者是構(gòu)造函數(shù)所帶的Comparator決定的順序。
                          SynchronousQueue:特殊的BlockingQueue,對(duì)其的操作必須是放和取交替完成的。

                 LinkedBlockingQueue和ArrayBlockingQueue比較起來,它們背后所用的數(shù)據(jù)結(jié)構(gòu)不一樣,導(dǎo)致LinkedBlockingQueue的數(shù)據(jù)吞吐量要大于ArrayBlockingQueue,但在線程數(shù)量很大時(shí)其性能的可預(yù)見性低于ArrayBlockingQueue。


          import java.util.concurrent.ArrayBlockingQueue;
          import java.util.concurrent.BlockingQueue;
          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;

          /**
           * BlockingQueue是一種特殊的Queue,若BlockingQueue是空的,
           * 從BlockingQueue取東西的操作將會(huì)被阻斷進(jìn)入等待狀態(tài)直到BlocingkQueue進(jìn)了新貨才會(huì)被喚醒。
           * 同樣,如果BlockingQueue是滿的任何試圖往里存東西的操作也會(huì)被阻斷進(jìn)入等待狀態(tài),
           * 直到BlockingQueue里有新的空間才會(huì)被喚醒繼續(xù)操作。
           * BlockingQueue提供的方法主要有:
           * add(anObject): 把a(bǔ)nObject加到BlockingQueue里,如果BlockingQueue可以容納返回true,否則拋出IllegalStateException異常。 
           * offer(anObject):把a(bǔ)nObject加到BlockingQueue里,如果BlockingQueue可以容納返回true,否則返回false。 
           * put(anObject):把a(bǔ)nObject加到BlockingQueue里,如果BlockingQueue沒有空間,調(diào)用此方法的線程被阻斷直到BlockingQueue里有新的空間再繼續(xù)。 
           * poll(time):取出BlockingQueue里排在首位的對(duì)象,若不能立即取出可等time參數(shù)規(guī)定的時(shí)間。取不到時(shí)返回null。 
           * take():取出BlockingQueue里排在首位的對(duì)象,若BlockingQueue為空,阻斷進(jìn)入等待狀態(tài)直到BlockingQueue有新的對(duì)象被加入為止。
           * 
           * 根據(jù)不同的需要BlockingQueue有4種具體實(shí)現(xiàn):
           * (1)ArrayBlockingQueue:規(guī)定大小的BlockingQueue,其構(gòu)造函數(shù)必須帶一個(gè)int參數(shù)來指明其大小。其所含的對(duì)象是以FIFO(先入先出)順序排序的。 
           * (2)LinkedBlockingQueue:大小不定的BlockingQueue,若其構(gòu)造函數(shù)帶一個(gè)規(guī)定大小的參數(shù),生成的BlockingQueue有大小限制,
           * 若不帶大小參數(shù),所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定。其所含的對(duì)象是以FIFO(先入先出)順序排序的。
           * LinkedBlockingQueue和ArrayBlockingQueue比較起來,它們背后所用的數(shù)據(jù)結(jié)構(gòu)不一樣,
           * 導(dǎo)致LinkedBlockingQueue的數(shù)據(jù)吞吐量要大于ArrayBlockingQueue,但在線程數(shù)量很大時(shí)其性能的可預(yù)見性低于ArrayBlockingQueue。 
           * (3)PriorityBlockingQueue:類似于LinkedBlockingQueue,但其所含對(duì)象的排序不是FIFO,而是依據(jù)對(duì)象的自然排序順序或者是構(gòu)造函數(shù)所帶的Comparator決定的順序。 
           * (4)SynchronousQueue:特殊的BlockingQueue,對(duì)其的操作必須是放和取交替完成的。
           * 
           * 下面是用BlockingQueue來實(shí)現(xiàn)Producer和Consumer的例子
           
          */

          public class BlockingQueueTest {

              
          /**
               * 定義裝蘋果的籃子
               
          */

              
          public static class Basket{
                  
          // 籃子,能夠容納3個(gè)蘋果
                  BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);
                  
                  
          // 生產(chǎn)蘋果,放入籃子
                  public void produce() throws InterruptedException{
                      
          // put方法放入一個(gè)蘋果,若basket滿了,等到basket有位置
                      basket.put("An apple");
                  }

                  
          // 消費(fèi)蘋果,從籃子中取走
                  public String consume() throws InterruptedException{
                      
          // get方法取出一個(gè)蘋果,若basket為空,等到basket有蘋果為止
                      return basket.take();
                  }

              }

              
          // 測試方法
              public static void testBasket() {
                  
          // 建立一個(gè)裝蘋果的籃子
                  final Basket basket = new Basket();
                  
          // 定義蘋果生產(chǎn)者
                  class Producer implements Runnable {
                      
          public void run() {
                          
          try {
                              
          while (true{
                                  
          // 生產(chǎn)蘋果
                                  System.out.println("生產(chǎn)者準(zhǔn)備生產(chǎn)蘋果:" 
                                          
          + System.currentTimeMillis());
                                  basket.produce();
                                  System.out.println(
          "生產(chǎn)者生產(chǎn)蘋果完畢:" 
                                          
          + System.currentTimeMillis());
                                  
          // 休眠300ms
                                  Thread.sleep(300);
                              }

                          }
           catch (InterruptedException ex) {
                          }

                      }

                  }

                  
          // 定義蘋果消費(fèi)者
                  class Consumer implements Runnable {
                      
          public void run() {
                          
          try {
                              
          while (true{
                                  
          // 消費(fèi)蘋果
                                  System.out.println("消費(fèi)者準(zhǔn)備消費(fèi)蘋果:" 
                                          
          + System.currentTimeMillis());
                                  basket.consume();
                                  System.out.println(
          "消費(fèi)者消費(fèi)蘋果完畢:" 
                                          
          + System.currentTimeMillis());
                                  
          // 休眠1000ms
                                  Thread.sleep(1000);
                              }

                          }
           catch (InterruptedException ex) {
                          }

                      }

                  }

                  
                  ExecutorService service 
          = Executors.newCachedThreadPool();
                  Producer producer 
          = new Producer();
                  Consumer consumer 
          = new Consumer();
                  service.submit(producer);
                  service.submit(consumer);
                  
          // 程序運(yùn)行5s后,所有任務(wù)停止
                  try {
                      Thread.sleep(
          5000);
                  }
           catch (InterruptedException e) {
                  }

                  service.shutdownNow();
              }


              
          public static void main(String[] args) {
                  BlockingQueueTest.testBasket();
              }

          }




                                                                                                                 --    學(xué)海無涯
                  

          主站蜘蛛池模板: 廊坊市| 色达县| 嘉禾县| 罗甸县| 武宣县| 辽阳县| 惠安县| 吴忠市| 桐乡市| 神农架林区| 项城市| 永康市| 孟州市| 科技| 菏泽市| 沙湾县| 磴口县| 林口县| 湘乡市| 双峰县| 万州区| 临洮县| 巨鹿县| 南陵县| 西丰县| 昌黎县| 蒙城县| 金塔县| 敦煌市| 佛山市| 新巴尔虎左旗| 聂荣县| 太康县| 寿光市| 武胜县| 永顺县| 吉木乃县| 湘潭市| 财经| 行唐县| 博爱县|