摘要:每個(gè)工作線程在結(jié)束前將門栓計(jì)數(shù)器減一,門栓的計(jì)數(shù)變?yōu)榫捅砻鞴ぷ魍瓿?。常用方法遞減鎖存器的計(jì)數(shù),如果計(jì)數(shù)到達(dá)零,則釋放所有等待的線程。使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線程被中斷或超出了指定的等待時(shí)間。
【同步器
java.util.concurrent包包含幾個(gè)能幫助人們管理相互合作的線程集的類。這些機(jī)制具有為線程直間的共用集結(jié)點(diǎn)模式提供的‘預(yù)制功能’。如果有一個(gè)相互合作的線程滿足這些行為模式之一,那么應(yīng)該直接使用提供的類庫而不是顯示的使用鎖與條件的集合。
【倒計(jì)時(shí)門栓一個(gè)倒計(jì)時(shí)門栓(CountDownlatch)讓一個(gè)線程集直到計(jì)數(shù)變?yōu)?.倒計(jì)時(shí)門栓是一次性的,一旦計(jì)數(shù)為0就不能再重用了。一個(gè)有用的特例是計(jì)數(shù)值為1的門栓。實(shí)現(xiàn)一個(gè)只能通過一次的門。線程在門外等待直到另一個(gè)線程將計(jì)數(shù)值變?yōu)?。舉例來講,假設(shè)一個(gè)線程集需要一些初始數(shù)據(jù)來完成工作。工作線程被啟動(dòng)并在,門外等候,另一個(gè)線程準(zhǔn)備數(shù)據(jù),當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),調(diào)用countDown(),所有的工作線程就可以繼續(xù)工作了。然后再使用一個(gè)門栓檢查什么時(shí)候工作線程全部運(yùn)行完成。每個(gè)工作線程在結(jié)束前將門栓計(jì)數(shù)器減一,門栓的計(jì)數(shù)變?yōu)?就表明工作完成。
【常用方法public void countDown():遞減鎖存器的計(jì)數(shù),如果計(jì)數(shù)到達(dá)零,則釋放所有等待的線程。如果當(dāng)前計(jì)數(shù)大于零,則將計(jì)數(shù)減少。如果新的計(jì)數(shù)為零,出于線程調(diào)度目的,將重新啟用所有的等待線程。如果當(dāng)前計(jì)數(shù)等于零,則不發(fā)生任何操作。
public boolean await():使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,如果當(dāng)前計(jì)數(shù)為零,則此方法立刻返回 true 值。
public boolean await(long timeout,TimeUnit unit) throws InterruptedException:使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線程被中斷或超出了指定的等待時(shí)間。如果當(dāng)前計(jì)數(shù)為零,則此方法立刻返回 true 值。如果當(dāng)前計(jì)數(shù)大于零,則出于線程調(diào)度目的,將禁用當(dāng)前線程,且在發(fā)生以下三種情況之一前,該線程將一直處于休眠狀態(tài):
由于調(diào)用 countDown() 方法,計(jì)數(shù)到達(dá)零;或者其他某個(gè)線程中斷當(dāng)前線程;或者已超出指定的等待時(shí)間。如果計(jì)數(shù)到達(dá)零,則該方法返回 true 值。
如果當(dāng)前線程:在進(jìn)入此方法時(shí)已經(jīng)設(shè)置了該線程的中斷狀態(tài);或者在等待時(shí)被中斷,則拋出 InterruptedException,并且清除當(dāng)前線程的已中斷狀態(tài)。
如果超出了指定的等待時(shí)間,則返回值為 false。如果該時(shí)間小于等于零,則此方法根本不會(huì)等待。
【例子模擬一個(gè)應(yīng)用程序:在正式開始工作前需要初始化數(shù)據(jù),初始化數(shù)據(jù)使用三個(gè)線程,正式執(zhí)行需要五個(gè)線程:
初始化線程
public class InitThread implements Runnable{ private CountDownLatch downLatch; private String name; public InitThread(CountDownLatch downLatch, String name){ this.downLatch = downLatch; this.name = name; } public void run() { this.doWork(); try{ TimeUnit.SECONDS.sleep(new Random().nextInt(10)); }catch(InterruptedException ie){ } System.out.println(this.name + "初始化數(shù)據(jù)完成"); //計(jì)數(shù)器減一 this.downLatch.countDown(); } private void doWork(){ System.out.println(this.name + "正在初始化數(shù)據(jù)... ..."); } }
初始化線程監(jiān)視器
/** * 檢測(cè)初始化數(shù)據(jù)監(jiān)視器,因?yàn)樾枰袛嗍欠癯跏蓟€程全部執(zhí)行完畢,這里用callable返回結(jié)果。runnable不能返回值所以無法判斷。 */ public class InitMonitor implements Callable{ private ExecutorService executor; private CountDownLatch initLatch; private List initThreads; public InitMonitor(ExecutorService executor){ this.executor = executor; //初始化線程:3個(gè) initLatch = new CountDownLatch(3); initThreads = Arrays.asList(new InitThread(initLatch,"InitOne"), new InitThread(initLatch,"InitTwo"), new InitThread(initLatch,"InitThree")); } public String call() { System.out.println("=========初始化START=========="); initThreads.stream().forEach(initThread -> executor.submit(initThread)); try { initLatch.await(); } catch (InterruptedException e) { } System.out.println("***********初始化END*************"); return "INIT_SUCCESS"; } }
工作線程
public class ExecuteThread implements Runnable{ private CountDownLatch downLatch; private String name; public ExecuteThread(CountDownLatch downLatch, String name){ this.downLatch = downLatch; this.name = name; } public void run() { this.doWork(); try{ TimeUnit.SECONDS.sleep(new Random().nextInt(10)); }catch(InterruptedException ie){ } System.out.println(this.name + "執(zhí)行完成"); //計(jì)數(shù)器減一 this.downLatch.countDown(); } private void doWork(){ System.out.println(this.name + "正在執(zhí)行... ..."); } }
工作線程監(jiān)視器
public class ExecuteMonitor implements Callable{ private ExecutorService executor; private CountDownLatch executeLatch; private List executeThreads; public ExecuteMonitor(ExecutorService executor){ this.executor = executor; //執(zhí)行線程:5個(gè) executeLatch = new CountDownLatch(5); executeThreads = Arrays.asList(new ExecuteThread(executeLatch,"ExecuteOne"), new ExecuteThread(executeLatch,"ExecuteTwo"), new ExecuteThread(executeLatch,"ExecuteThree"), new ExecuteThread(executeLatch,"ExecuteFour"), new ExecuteThread(executeLatch,"ExecuteFive")); } public String call() { System.out.println("========執(zhí)行START========"); executeThreads.stream().forEach(executeThread -> executor.submit(executeThread)); try { executeLatch.await(); } catch (InterruptedException e) { } System.out.println("*********執(zhí)行END*********"); return "EXECUTE_SUCCESS"; } }
應(yīng)用程序
public class Application implements Runnable{ private ExecutorService executor; private InitMonitor initMonitor; private ExecuteMonitor executeMonitor; public Application(ExecutorService executor){ this.executor = executor; initMonitor = new InitMonitor(executor); executeMonitor = new ExecuteMonitor(executor); } @Override public void run() { System.out.println("===============應(yīng)用程序執(zhí)行開始====================》》》"); FutureTaskinitTask = new FutureTask (initMonitor); executor.submit(initTask); try { //如果初始化成功開始執(zhí)行工作線程,在調(diào)用get()時(shí),如果沒有執(zhí)行完成會(huì)自動(dòng)阻塞,所以這里不需要使用isDone檢測(cè)。 if("INIT_SUCCESS".equals(initTask.get())){ FutureTask executeTask = new FutureTask (executeMonitor); executor.submit(executeTask); if("EXECUTE_SUCCESS".equals(executeTask.get())){ executor.shutdown(); System.out.println("===============應(yīng)用程序執(zhí)行完畢===================="); } } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
客戶端
客戶端一定盡量簡介,所有細(xì)節(jié)全部屏蔽,這里只留下一個(gè)可以自定義線程池給用戶自行選擇
public class Test { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(10); Application application = new Application(executor); application.run(); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68090.html
摘要:考慮大量線程運(yùn)行在一次計(jì)算的不同部分的情形。一旦所有的線程都到達(dá)了這個(gè)柵欄,柵欄就撤銷,線程可以繼續(xù)運(yùn)行。那些已經(jīng)在等待的線程立即中止的調(diào)用。如果在執(zhí)行屏障操作過程中發(fā)生異常,則該異常將傳播到當(dāng)前線程中,并將置于損壞狀態(tài)。 【同步器 java.util.concurrent包包含幾個(gè)能幫助人們管理相互合作的線程集的類。這些機(jī)制具有為線程直間的共用集結(jié)點(diǎn)模式提供的‘預(yù)制功能’。如果有一個(gè)...
摘要:今天給大家總結(jié)一下,面試中出鏡率很高的幾個(gè)多線程面試題,希望對(duì)大家學(xué)習(xí)和面試都能有所幫助。指令重排在單線程環(huán)境下不會(huì)出先問題,但是在多線程環(huán)境下會(huì)導(dǎo)致一個(gè)線程獲得還沒有初始化的實(shí)例。使用可以禁止的指令重排,保證在多線程環(huán)境下也能正常運(yùn)行。 下面最近發(fā)的一些并發(fā)編程的文章匯總,通過閱讀這些文章大家再看大廠面試中的并發(fā)編程問題就沒有那么頭疼了。今天給大家總結(jié)一下,面試中出鏡率很高的幾個(gè)多線...
摘要:為了通過信號(hào)量,線程通過調(diào)用請(qǐng)求許可。許可的數(shù)目是固定的,由此限制了線程通過的數(shù)量。當(dāng)設(shè)置為時(shí)默認(rèn)也是,此類不對(duì)線程獲取許可的順序做任何保證。 【同步器 java.util.concurrent包包含幾個(gè)能幫助人們管理相互合作的線程集的類。這些機(jī)制具有為線程直間的共用集結(jié)點(diǎn)模式提供的‘預(yù)制功能’。如果有一個(gè)相互合作的線程滿足這些行為模式之一,那么應(yīng)該直接使用提供的類庫而不是顯示的使用鎖...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢娝氖褂?,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢娝氖褂茫陂_始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
閱讀 718·2023-04-25 17:54
閱讀 2974·2021-11-18 10:02
閱讀 1137·2021-09-28 09:35
閱讀 653·2021-09-22 15:18
閱讀 2854·2021-09-03 10:49
閱讀 3056·2021-08-10 09:42
閱讀 2577·2019-08-29 16:24
閱讀 1260·2019-08-29 15:08