摘要:多線程同步工具箱之篇前言的多線程協(xié)調(diào)工具,,,都是在多線程代碼中使用比較多的工具類之一。毫不夸張的說,這幾個類,是等同于解決多線程問的包,實在有必要添加到程序員的工具箱里面。
Java多線程同步工具箱之CountDownLatch篇 前言
Java的多線程協(xié)調(diào)工具CountDownLatch,Semaphore,CyclicBarrier,ReadWriteLock都是在多線程代碼中使用比較多的工具類之一。掌握及理解這幾個類的實現(xiàn),對解決和理解多線程中復(fù)雜的業(yè)務(wù)狀況有很重要的作用。毫不夸張的說,這幾個類,是等同于解決多線程問的java.util包,實在有必要添加到程序員的工具箱里面。
此次文章,將分幾篇總結(jié)及解讀一下這些工具類的具體用法和范例,最后,希望可以再深入一點去理解這幾個多線程工具的實現(xiàn)。
1. CountDownLatch(倒數(shù)鎖)CountDownLatch是一個常用的多線程協(xié)調(diào)工具:主要為協(xié)調(diào)一個或多個線程完成后,主線程進行某個操作的功能。
Latch原指門閂,CountDownLatch譯為倒數(shù)鎖倒是不太過分??梢岳斫鉃椋菏褂弥骶€程初始化一個有N個子鎖的鎖,任務(wù)開始的時,分配給N個線程每個線程持有一把鑰匙,每個線程到某個狀態(tài)后(一般為完成),可以使用線程持有的鑰匙打開主線程持有的鎖,直至所有N個鎖都被打開,主線程才可以繼續(xù)其他任務(wù)。
1.1 API從API上看我們可以關(guān)注下面幾個CountDownLatch提供了幾個接口:
構(gòu)造方法CountDownLatch(int)
構(gòu)造方法十分簡單,注入一個int,初始化倒數(shù)鎖的大小。
await()
等待所有鎖被解開,該函數(shù)還有一個帶等待時長及等待時間單位的重寫await(long time, TimeUnit unit),用于避免過度的等待造成的死鎖。
countDown()
解鎖方法,解開一個鎖,知道持有的鎖數(shù)量為0,則接觸await的狀態(tài)。
getCount()
獲取當(dāng)前的剩余的鎖的數(shù)量。
1.2 范例在范例中,我們簡單的使用一個主線程,發(fā)起若干個子線程,讓子線程進行休眠的例子作為測試倒數(shù),讓各個子線程導(dǎo)數(shù)完通知解鎖,主線程會被在所有子線程完成解鎖后通知所有任務(wù)完成。
1.2.1 使用倒數(shù)鎖前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; // 秒數(shù)*1000毫秒 = 實際等待毫秒數(shù) 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"); } } }
可以從結(jié)果中看到,所有的線程啟動后,主線程就會立刻退出,子線程會在完成各自的任務(wù)后再退出。
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 使用倒數(shù)鎖后
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 { // 等待所有的鎖被(倒數(shù))釋放 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; // 秒數(shù)*1000毫秒 = 實際等待毫秒數(shù) 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"); } } }
可以從結(jié)果中看到,所有的線程啟動后,都會等到所有線程完成等待后才結(jié)束。
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小結(jié)
CountDownLatch(倒數(shù)鎖)適用于需要等待子線程完成后,統(tǒng)一進行操作的一些操作。更可以結(jié)合FutureTask的相關(guān)接口,取回子線程的結(jié)果,對結(jié)果統(tǒng)一搜集處理。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/76682.html
摘要:前言之前學(xué)多線程的時候沒有學(xué)習(xí)線程的同步工具類輔助類。而其它線程完成自己的操作后,調(diào)用使計數(shù)器減。信號量控制一組線程同時執(zhí)行。 前言 之前學(xué)多線程的時候沒有學(xué)習(xí)線程的同步工具類(輔助類)。ps:當(dāng)時覺得暫時用不上,認為是挺高深的知識點就沒去管了.. 在前幾天,朋友發(fā)了一篇比較好的Semaphore文章過來,然后在瀏覽博客的時候又發(fā)現(xiàn)面試還會考,那還是挺重要的知識點。于是花了點時間去了解...
摘要:好了,繼續(xù)向下執(zhí)行,嘗試獲取鎖失敗后,會調(diào)用首先通過方法,將包裝成共享結(jié)點,插入等待隊列,插入完成后隊列結(jié)構(gòu)如下然后會進入自旋操作,先嘗試獲取一次鎖,顯然此時是獲取失敗的主線程還未調(diào)用,同步狀態(tài)還是。 showImg(https://segmentfault.com/img/remote/1460000016012541); 本文首發(fā)于一世流云的專欄:https://segmentfa...
摘要:在多線程編程中我們會遇到很多需要使用線程同步機制去解決的并發(fā)問題,而這些同步機制就是多線程編程中影響正確性和運行效率的重中之重。這五個方法之所以能指定同步器的行為,則是因為中的其他方法就是通過對這五個方法的調(diào)用來實現(xiàn)的。 在多線程編程中我們會遇到很多需要使用線程同步機制去解決的并發(fā)問題,而這些同步機制就是多線程編程中影響正確性和運行效率的重中之重。這不禁讓我感到好奇,這些同步機制是如何...
摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請參考死磕同步系列之。目前國內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現(xiàn)原理? (4)volatile的缺陷? 簡介 volatile...
閱讀 3136·2021-11-24 11:14
閱讀 3660·2021-11-22 15:22
閱讀 3277·2021-09-27 13:36
閱讀 796·2021-08-31 14:29
閱讀 1384·2019-08-30 15:55
閱讀 1853·2019-08-29 17:29
閱讀 1193·2019-08-29 16:24
閱讀 2528·2019-08-26 13:48