1. 程式人生 > >Java --- 併發庫concurrent包學習總結

Java --- 併發庫concurrent包學習總結


下面的例子演示了這個阻塞佇列的基本功能。

  1. import java.util.concurrent.BlockingQueue;  
  2. import java.util.concurrent.ExecutorService;  
  3. import java.util.concurrent.Executors;  
  4. import java.util.concurrent.LinkedBlockingQueue;  
  5. publicclass MyBlockingQueue extends Thread {  
  6.     publicstatic BlockingQueue<String> queue = 
    new LinkedBlockingQueue<String>(3);  
  7.     privateint index;  
  8.     public MyBlockingQueue(int i) {  
  9.         this.index = i;  
  10.     }  
  11.     publicvoid run() {  
  12.         try {  
  13.             queue.put(String.valueOf(this.index));  
  14.             System.out.println("{" + this.index + "} in queue!"
    );  
  15.         } catch (Exception e) {  
  16.             e.printStackTrace();  
  17.         }  
  18.     }  
  19.     publicstaticvoid main(String args[]) {  
  20.         ExecutorService service = Executors.newCachedThreadPool();  
  21.         for (int i = 0; i < 10; i++) {  
  22.             service.submit(new MyBlockingQueue(i));  
  23.         }  
  24.         Thread thread = new Thread() {  
  25.             publicvoid run() {  
  26.                 try {  
  27.                     while (true) {  
  28.                         Thread.sleep((int) (Math.random() * 1000));  
  29.                         if (MyBlockingQueue.queue.isEmpty())  
  30.                             break;  
  31.                         String str = MyBlockingQueue.queue.take();  
  32.                         System.out.println(str + " has take!");  
  33.                     }  
  34.                 } catch (Exception e) {  
  35.                     e.printStackTrace();  
  36.                 }  
  37.             }  
  38.         };  
  39.         service.submit(thread);  
  40.         service.shutdown();  
  41.     }  
  42. }  

---------------------執行結果-----------------
{0} in queue!
{1} in queue!
{2} in queue!
{3} in queue!
0 has take!
{4} in queue!
1 has take!
{6} in queue!
2 has take!
{7} in queue!
3 has take!
{8} in queue!
4 has take!
{5} in queue!
6 has take!
{9} in queue!
7 has take!
8 has take!
5 has take!
9 has take!
-----------------------------------------

CompletionService

我們現在在Java中使用多執行緒通常不會直接用Thread物件了,而是會用到java.util.concurrent包下的ExecutorService類來初始化一個執行緒池供我們使用。之前我一直習慣自己維護一個list儲存submit的callable task所返回的Future物件。在主執行緒中遍歷這個list並呼叫Future的get()方法取到Task的返回值。但是,我在很多地方會看到一些程式碼通過CompletionService包裝ExecutorService,然後呼叫其take()方法去取Future物件。以前沒研究過這兩者之間的區別。今天看了原始碼之後就明白了。這兩者最主要的區別在於submit的task不一定是按照加入自己維護的list順序完成的。
從list中遍歷的每個Future物件並不一定處於完成狀態,這時呼叫get()方法就會被阻塞住,如果系統是設計成每個執行緒完成後就能根據其結果繼續做後面的事,這樣對於處於list後面的但是先完成的執行緒就會增加了額外的等待時間。而CompletionService的實現是維護一個儲存Future物件的BlockingQueue。只有當這個Future物件狀態是結束的時候,才會加入到這個Queue中,take()方法其實就是Producer-Consumer中的Consumer。它會從Queue中取出Future物件,如果Queue是空的,就會阻塞在那裡,直到有完成的Future物件加入到Queue中。
所以,先完成的必定先被取出。這樣就減少了不必要的等待時間。ExecutorCompletionService 類提供了此方法的一個實現。

  1. import java.util.concurrent.Callable;  
  2. import java.util.concurrent.CompletionService;  
  3. import java.util.concurrent.ExecutorCompletionService;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.Executors;  
  6. publicclass MyCompletionService implements Callable<String> {  
  7.     privateint id;  
  8.     public MyCompletionService(int i) {  
  9.         this.id = i;  
  10.     }  
  11.     publicstaticvoid main(String[] args) throws Exception {  
  12.         ExecutorService service = Executors.newCachedThreadPool();  
  13.         CompletionService<String> completion = new ExecutorCompletionService<String>(service);  
  14.         for (int i = 0; i < 10; i++) {  
  15.             completion.submit(new MyCompletionService(i));  
  16.         }  
  17.         for (int i = 0; i < 10; i++) {  
  18.             System.out.println(completion.take().get());  
  19.         }  
  20.         service.shutdown();  
  21.     }  
  22.     public String call() throws Exception {  
  23.         Integer time = (int) (Math.random() * 1000);  
  24.         try {  
  25.             System.out.println(this.id + " start");  
  26.             Thread.sleep(time);  
  27.             System.out.println(this.id + " end");  
  28.         }catch (Exception e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.         returnthis.id + ":" + time;  
  32.     }  
  33. }  

CountDownLatch

一個同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。
用給定的計數 初始化 CountDownLatch。由於呼叫了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。
之後,會釋放所有等待的執行緒,await 的所有後續呼叫都將立即返回。這種現象只出現一次——計數無法被重置。如果需要重置計數,請考慮使用 CyclicBarrier。
CountDownLatch 是一個通用同步工具,它有很多用途。將計數 1 初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,
或入口:在通過呼叫 countDown() 的執行緒開啟入口前,所有呼叫 await 的執行緒都一直在入口處等待。
用 N 初始化的 CountDownLatch 可以使一個執行緒在 N 個執行緒完成某項操作之前一直等待,或者使其在某項操作完成 N 次之前一直等待。
CountDownLatch 的一個有用特性是,它不要求呼叫 countDown 方法的執行緒等到計數到達零時才繼續,而在所有執行緒都能通過之前,它只是阻止任何執行緒繼續通過一個 await。

下面的例子是別人寫的,非常形象。

  1. import java.util.concurrent.CountDownLatch;  
  2. import java.util.concurrent.ExecutorService;  
  3. import java.util.concurrent.Executors;  
  4. publicclass TestCountDownLatch {  
  5.     publicstaticvoid main(String[] args) throws InterruptedException {  
  6.         // 開始的倒數鎖
  7.         final CountDownLatch begin = new CountDownLatch(1);  
  8.         // 結束的倒數鎖
  9.         final CountDownLatch end = new CountDownLatch(10);  
  10.         // 十名選手
  11.         final ExecutorService exec = Executors.newFixedThreadPool(10);  
  12.         for (int index = 0; index < 10; index++) {  
  13.             finalint NO = index + 1;  
  14.             Runnable run = new Runnable() {  
  15.                 publicvoid run() {  
  16.                     

    相關推薦

    Java --- 併發concurrent學習總結

    下面的例子演示了這個阻塞佇列的基本功能。 import java.util.concurrent.BlockingQueue;   import java.util.concurrent.ExecutorService;   import java.util.concur

    多執行緒併發學習總結(一)Lock鎖

    為什麼需要Lock鎖 1.因為我們需要有一種機制可以不讓等待的執行緒一直無期限地等待下去(比如只等待一定的時間或者能夠響應中斷),通過Lock就可以辦到。 2.通過Lock可以知道執行緒有沒有成功獲取到鎖 3.Lock鎖相當於汽車中的手動擋,相比synchron

    java Concurrent學習筆記(五):Semaphore

    一、Semaphore 是什麼  訊號量Semaphore是一個併發工具類,用來控制可同時併發的執行緒數,其內部維護了一組虛擬許可,建構函式初始化的時候可以指定許可的總數量 每次執行緒執行操作時先通過acquire方法獲得許可,執行緒獲得許可後Semaphore 的許可數量會減1,執行完畢再通過

    java Concurrent學習筆記(七):ConcurrentHashMap

    (注意:以下講解的ConcurrentHashMap是jdk 1.8的) 一、ConcurrentHashMap的資料結構     ConcurrentHashMap在1.8中的實現,相比於1.7的版本基本上全部都變掉了。 首先,取消了Segment分段鎖的資料結構,

    java 並發(concurrent)源碼分析

    ctf cond oid 方法名 current 並不會 對象的引用 p s 需要 參考連接: http://www.cnblogs.com/luoxn28/p/6059881.html http://www.cnblogs.com/java-zhao/p/5140158.

    20165233 Java第二、三章學習總結

    符號 int() 編譯運行 while 常量 java color ima 進行 2017-2018-2 《Java程序設計》第二周學習總結 教材學習內容總結 第二、三章 ch2 標識符與關鍵字 基本數據類型: 邏輯類型:boolean 整數類型:int、byte、sho

    java微職位】51CTO學習總結

    【java微職位】51CTO學習總結【java微職位】51CTO學習總結通過半年的學習終於學完了本課程按時結業,通過這個課程的學習自己感覺很有收獲,回想這半年來的學習時間還是有些感慨,做下小的總結。一、 學習習慣的養成。學習是一個連貫的過程,也是一件需要持之以恒的事情。java微職位這個課程涵蓋的東西非常廣

    python導學習總結

    int 通過 print 導包 類名 定義 分享圖片 test UNC python初學者,對於導包糾結了不少時間,總結分享,持續前進~ Python導包的兩種方法:   1.1 from 包.模塊 import 方法名,調用時直接使用方法名()   1.2 from

    Java】 Spring 框架初步學習總結(一)簡單實現 IoC 和 AOP

    1.0 其中 表示 只需要 第一篇 否則 info fin pojo   Spring 是一個開源的設計層面的輕量級框架,Spring 的好處網上有太多,這裏就不在贅述。   IoC 控制反轉和 AOP 面向切面編程是 Spring 的兩個重要特性。   IoC(Inver

    張雲飛201771010143《面向對象程序設計(java)》第一周學習總結

    sta 開放 nbsp 相同 知識 font 程序設計 ria 兩個 第一部分:課程準備部分 填寫課程學習平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com https://www.cnblogs.com/Fairber/

    王艷 201771010127《面向對象程序設計(java)》第一周學習總結

    文件的 會有 工具 過程 cmd 名稱 開發環境 機器 ext 王艷 201771010127《面向對象程序設計(java)》第一周學習總結 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com

    楊蓉慶201771010135《面向對象程序設計(java)》第一周學習總結

    開發環境 嘗試 總結 cin 一次 9.png 助教 course borde 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com 艾特大家 程序設計評測:https://pint

    趙棟 201771010137 《面向對象程序設計(java)》第一周學習總結

    world 單詞 load .cn pri 保存文件 新建 過程 應該 《面向對象程序設計(java)》第一周學習總結第一部分:課程準備部分 平臺名稱 註冊賬號 博客園:www.cnblogs.com/ https://www.cnblogs.

    達拉草201771010105《面向對象程序設計(java)》第一周學習總結

    www 創建 垃圾收集 clas 本地文件 常用 進行 重用 等等 達拉草201771010105《面向對象程序設計(java)》第一周學習總結 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.c

    孔維瀅201771010110《面向對象程序設計(java)》第一周學習總結

    環境變量 ali 源文件 height 總結 img 實例 zip logs 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號 平臺名稱 註冊賬號 博客園:www.cnblogs.com Weiron 程序設計評測:https://pintia.cn/ 11

    201771010108韓臘梅《面向對象程序設計(java)》第一周學習總結

    成員 體系結構 簡單的 2.7 -i ssp 電腦 文件夾 客戶端 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com 木子林 程序設計評測:https://pintia.cn/

    狄慧201771010104《面向對象程序設計(java)》第一周學習總結

    修改 java語法 第一部分 cells 虛基類 面向對象 數據庫 學習 java開發工具 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com https://www.cnblogs.co

    李婷華 201771010113 《面向對象程序設計(java)》第一周學習總結

    idt 很多 轉換 基本命令 理解 第一部分 令行 操作 嚴格 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com 薄荷藍莓 程序設計評測:https://pintia.cn/

    201771010103 陳亞茹 《面向對象程序設計(java)》第一周學習總結

    cell 自己 第二部分 蠕蟲 bsp core 9.png 完成後 處理 本人學號《面向對象程序設計(java)》第一周學習總結 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblogs.com ht

    張季躍201771010139《面向對象程序設計(java)》第一周學習總結(改)

    ani code 免費 封裝 java版 ++ 數字 tcp intel 張季躍201771010139《面向對象程序設計(java)》第一周學習總結 第一部分:課程準備部分 填寫課程學習 平臺註冊賬號, 平臺名稱 註冊賬號 博客園:www.cnblog