摘要:多線程同步工具箱之篇前言的多線程協調工具,,,都是在多線程代碼中使用比較多的工具類之一。毫不夸張的說,這幾個類,是等同于解決多線程問的包,實在有必要添加到程序員的工具箱里面。
Java多線程同步工具箱之CountDownLatch篇 前言
Java的多線程協調工具CountDownLatch,Semaphore,CyclicBarrier,ReadWriteLock都是在多線程代碼中使用比較多的工具類之一。掌握及理解這幾個類的實現,對解決和理解多線程中復雜的業務狀況有很重要的作用。毫不夸張的說,這幾個類,是等同于解決多線程問的java.util包,實在有必要添加到程序員的工具箱里面。
此次文章,將分幾篇總結及解讀一下這些工具類的具體用法和范例,最后,希望可以再深入一點去理解這幾個多線程工具的實現。
1. CountDownLatch(倒數鎖)CountDownLatch是一個常用的多線程協調工具:主要為協調一個或多個線程完成后,主線程進行某個操作的功能。
Latch原指門閂,CountDownLatch譯為倒數鎖倒是不太過分。可以理解為:使用主線程初始化一個有N個子鎖的鎖,任務開始的時,分配給N個線程每個線程持有一把鑰匙,每個線程到某個狀態后(一般為完成),可以使用線程持有的鑰匙打開主線程持有的鎖,直至所有N個鎖都被打開,主線程才可以繼續其他任務。
1.1 API從API上看我們可以關注下面幾個CountDownLatch提供了幾個接口:
構造方法CountDownLatch(int)
構造方法十分簡單,注入一個int,初始化倒數鎖的大小。
await()
等待所有鎖被解開,該函數還有一個帶等待時長及等待時間單位的重寫await(long time, TimeUnit unit),用于避免過度的等待造成的死鎖。
countDown()
解鎖方法,解開一個鎖,知道持有的鎖數量為0,則接觸await的狀態。
getCount()
獲取當前的剩余的鎖的數量。
1.2 范例在范例中,我們簡單的使用一個主線程,發起若干個子線程,讓子線程進行休眠的例子作為測試倒數,讓各個子線程導數完通知解鎖,主線程會被在所有子線程完成解鎖后通知所有任務完成。
1.2.1 使用倒數鎖前import java.util.concurrent.CountDownLatch; import java.util.logging.Logger; public class App { static Logger log = Logger.getAnonymousLogger(); public static void main(String[] args) { for (int index = 0; index < 10; index++) { new Thread(new SubThread(index, index)).start(); } // 所有的線程都完成了 log.info("all thread finished"); } }
import java.util.concurrent.CountDownLatch; import java.util.logging.Logger; public class SubThread implements Runnable { private int id; private int waitSecond; static Logger log = Logger.getAnonymousLogger(); public SubThread(int id, int waitSecond) { this.id = id; // 秒數*1000毫秒 = 實際等待毫秒數 this.waitSecond = waitSecond * 1000; } public void run() { try { log.info("Thread " + id + " started."); // 讓Thread再飛一會兒 Thread.sleep(waitSecond); log.info("Thread " + id + " end."); // 通知完成 } catch (InterruptedException e) { log.config("error"); } } }
可以從結果中看到,所有的線程啟動后,主線程就會立刻退出,子線程會在完成各自的任務后再退出。
Aug 09, 2018 6:43:22 PM online.tangbk.demo.thead.SubThread run INFO: Thread 3 started. ... ... Aug 09, 2018 6:43:22 PM online.tangbk.demo.thead.App main INFO: all thread finished Aug 09, 2018 6:43:22 PM online.tangbk.demo.thead.SubThread run INFO: Thread 8 started. ... ... Aug 09, 2018 6:43:31 PM online.tangbk.demo.thead.SubThread run INFO: Thread 9 end.1.2.2 使用倒數鎖后
import java.util.concurrent.CountDownLatch; import java.util.logging.Logger; public class App { static Logger log = Logger.getAnonymousLogger(); public static void main(String[] args) { // 初始化10個線程的鎖 CountDownLatch cdl = new CountDownLatch(10); for (int index = 0; index < 10; index++) { // 將鎖傳給子線程 new Thread(new SubThread(index, index, cdl)).start(); } try { // 等待所有的鎖被(倒數)釋放 cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } // 所有的線程都完成了 log.info("all thread finished"); } }
import java.util.concurrent.CountDownLatch; import java.util.logging.Logger; public class SubThread implements Runnable { private int id; private int waitSecond; private CountDownLatch cdl; static Logger log = Logger.getAnonymousLogger(); public SubThread(int id, int waitSecond, CountDownLatch cdl) { this.id = id; // 秒數*1000毫秒 = 實際等待毫秒數 this.waitSecond = waitSecond * 1000; this.cdl = cdl; } public void run() { try { log.info("Thread " + id + " started."); // 讓Thread再飛一會兒 Thread.sleep(waitSecond); cdl.countDown(); log.info("Thread " + id + " end."); // 通知完成 } catch (InterruptedException e) { log.config("error"); } } }
可以從結果中看到,所有的線程啟動后,都會等到所有線程完成等待后才結束。
Aug 09, 2018 6:29:20 PM online.tangbk.demo.thead.SubThread run INFO: Thread 2 started. Aug 09, 2018 6:29:20 PM online.tangbk.demo.thead.SubThread run INFO: Thread 3 started. Aug 09, 2018 6:29:20 PM online.tangbk.demo.thead.SubThread run INFO: Thread 1 started. Aug 09, 2018 6:29:20 PM online.tangbk.demo.thead.SubThread run INFO: Thread 0 started. ... ... Aug 09, 2018 6:29:28 PM online.tangbk.demo.thead.SubThread run INFO: Thread 8 end. Aug 09, 2018 6:29:29 PM online.tangbk.demo.thead.SubThread run INFO: Thread 9 end. Aug 09, 2018 6:29:29 PM online.tangbk.demo.thead.App main INFO: all thread finished1.3 CountDownLatch小結
CountDownLatch(倒數鎖)適用于需要等待子線程完成后,統一進行操作的一些操作。更可以結合FutureTask的相關接口,取回子線程的結果,對結果統一搜集處理。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/76682.html
摘要:前言之前學多線程的時候沒有學習線程的同步工具類輔助類。而其它線程完成自己的操作后,調用使計數器減。信號量控制一組線程同時執行。 前言 之前學多線程的時候沒有學習線程的同步工具類(輔助類)。ps:當時覺得暫時用不上,認為是挺高深的知識點就沒去管了.. 在前幾天,朋友發了一篇比較好的Semaphore文章過來,然后在瀏覽博客的時候又發現面試還會考,那還是挺重要的知識點。于是花了點時間去了解...
摘要:好了,繼續向下執行,嘗試獲取鎖失敗后,會調用首先通過方法,將包裝成共享結點,插入等待隊列,插入完成后隊列結構如下然后會進入自旋操作,先嘗試獲取一次鎖,顯然此時是獲取失敗的主線程還未調用,同步狀態還是。 showImg(https://segmentfault.com/img/remote/1460000016012541); 本文首發于一世流云的專欄:https://segmentfa...
摘要:在多線程編程中我們會遇到很多需要使用線程同步機制去解決的并發問題,而這些同步機制就是多線程編程中影響正確性和運行效率的重中之重。這五個方法之所以能指定同步器的行為,則是因為中的其他方法就是通過對這五個方法的調用來實現的。 在多線程編程中我們會遇到很多需要使用線程同步機制去解決的并發問題,而這些同步機制就是多線程編程中影響正確性和運行效率的重中之重。這不禁讓我感到好奇,這些同步機制是如何...
摘要:前半句是指線程內表現為串行的語義,后半句是指指令重排序現象和工作內存和主內存同步延遲現象。關于內存模型的講解請參考死磕同步系列之。目前國內市面上的關于內存屏障的講解基本不會超過這三篇文章,包括相關書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現原理? (4)volatile的缺陷? 簡介 volatile...
閱讀 3083·2021-11-24 11:14
閱讀 3530·2021-11-22 15:22
閱讀 3216·2021-09-27 13:36
閱讀 727·2021-08-31 14:29
閱讀 1336·2019-08-30 15:55
閱讀 1769·2019-08-29 17:29
閱讀 1154·2019-08-29 16:24
閱讀 2420·2019-08-26 13:48