多線程之同步器:
假設(shè)有A,B 兩個任務(wù)需要執(zhí)行电媳,A耗時3分鐘喇嘱,B耗時4分鐘
常規(guī)方法是???
A();
B() ;
?...? ? 總耗時7分鐘
但是如果想縮短時間信夫,且A B在執(zhí)行中沒有對同一資源的爭奪仿野,那么
可以開啟兩個線程铣减,分別執(zhí)行A,B? ?Java提供了三種創(chuàng)建線程的方法
1 通過實現(xiàn)Runnable 接口;
2 通過繼承Thread 類本身脚作;
2 通過Callable和Future 創(chuàng)建線程葫哗。
此外,spring 可以通過TaskExcutor 任務(wù)執(zhí)行器來實現(xiàn)多線程
線程1{ A() }
線程2{ B() }
...總耗時4分鐘
進程會在開啟兩個進程執(zhí)行A 球涛,B后劣针,繼續(xù)執(zhí)行接下來的代碼而不必等待A B結(jié)束。
在一些情況下亿扁,我們接下來的代碼(方法C)可能要用到A B 計算后的結(jié)果捺典,那么該怎么設(shè)置程序等待A B 都運行結(jié)束呢?
線程同步器完美解決~
在JDK1.5以后从祝,java.util.concurrent包提供了兩個工具類CounDownLatch類和CyclicBarrier類襟己。
CountDownLatch是一個同步計數(shù)器,能夠保證在其他線程完成某一個業(yè)務(wù)操作前牍陌,當(dāng)前線程一直處于等待/阻塞狀態(tài)擎浴。具體來說,這個計數(shù)器將會從給定的某一個數(shù)值count開始毒涧,通過countDown()方法的調(diào)用進行倒數(shù)贮预。當(dāng)執(zhí)行某一次countDown()操作后,計數(shù)器的count數(shù)值等于0契讲,所有調(diào)用了await()方法的線程仿吞,就解除等待/阻塞狀態(tài)繼續(xù)執(zhí)行。
// 同步計數(shù)器從2開始計數(shù)
finalCountDownLatch countDownLatch =newCountDownLatch(2);
// 啟動子線程捡偏,處理A B
Thread childThreadA =newThread() {
????????@Override
????????public void run(){
? ? ? ? ? ? ? ? synchronized(this){
????????????????????????try{
????????????????????????????A();
????????????????????????}catch(InterruptedException e) {
???????????????????????????????TestCountDownLatch.LOGGER.error(e.getMessage(), e);
????????????????????????}
????????????}
????????????// 完成業(yè)務(wù)處理過程唤冈,計數(shù)器-1
????????????countDownLatch.countDown();
????????}
};
Thread childThreadB =newThread() {
????????@Override
????????public void run(){
synchronized(this){
????????????????????????try{
? ? ? ? ? ? ? ? ? ? ? ? ? ? B();
????????????????????????}catch(InterruptedException e) {
???????????????????????????????TestCountDownLatch.LOGGER.error(e.getMessage(), e);
????????????????????????}
????????????}
????????????// 完成業(yè)務(wù)處理過程,計數(shù)器-1
????????????countDownLatch.countDown();
????????}
};
childThreadA.start();
childThreadB.start();
// 等待所有子線程的業(yè)務(wù)都處理完成(計數(shù)器的count為0時)?
?countDownLatch.await();
c();
CyclicBarrier也是同步計數(shù)工具霹琼,不同的是CyclicBarrier的計數(shù)是循環(huán)進行的务傲,而且也不需要向CountDownLatch那樣顯示的調(diào)用countDown進行減一操作。當(dāng)CyclicBarrier的計數(shù)周期設(shè)置為n的時候枣申,每當(dāng)有n個進程進入阻塞等待,CyclicBarrier就解除這n個進程的阻塞狀態(tài)看杭。所以可以理解為CyclicBarrier的計數(shù)功能是可以重復(fù)使用的忠藤。