CyclicBarrier與CountDownLatch的區(qū)別

CyclicBarrier簡介

CyclicBarrier 的字面意思是可循環(huán)(Cyclic)使用的屏障(Barrier)。它要做的事情是,讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最后一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續(xù)干活。線程進入屏障通過CyclicBarrier的await()方法。
CyclicBarrier默認的構(gòu)造方法是CyclicBarrier(int parties),其參數(shù)表示屏障攔截的線程數(shù)量,每個線程調(diào)用await方法告訴CyclicBarrier我已經(jīng)到達了屏障,然后當(dāng)前線程被阻塞。
CyclicBarrier還提供一個更高級的構(gòu)造函數(shù)CyclicBarrier(int parties, Runnable barrierAction),用于在線程到達屏障時,優(yōu)先執(zhí)行barrierAction這個Runnable對象,方便處理更復(fù)雜的業(yè)務(wù)場景。

await方法

調(diào)用await方法的線程告訴CyclicBarrier自己已經(jīng)到達同步點,然后當(dāng)前線程被阻塞。直到parties個參與線程調(diào)用了await方法,解除鎖定狀態(tài),CyclicBarrier同樣提供帶超時時間的await和不帶超時時間的await方法:


public int await() throws InterruptedException, BrokenBarrierException {
    try {
        // 不超時等待
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}


public int await(long timeout, TimeUnit unit)
    throws InterruptedException,
            BrokenBarrierException,
            TimeoutException {
    return dowait(true, unit.toNanos(timeout));
}

實例

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest {
    private static class NormalTask implements Runnable {
        CyclicBarrier barrier;

        NormalTask(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        @Override
        public void run() {        
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread().getName()+"時間"+System.currentTimeMillis());
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis() + " first step finished");
            
        }
    }
    private static class FinalTask implements Runnable {
        public FinalTask() {
            
        }
        @Override
        public void run() {
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() + " second step finished");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //第一個2表示當(dāng)有2個線程調(diào)用await方法時解鎖,第二個參數(shù)是解鎖后優(yōu)先執(zhí)行線程
        CyclicBarrier barrier = new CyclicBarrier(2,new FinalTask());
        new Thread(new NormalTask(barrier),"線程1").start();
        new Thread(new NormalTask(barrier),"線程2").start();
    }
}

執(zhí)行結(jié)果:

線程1時間1587799990409
線程2時間1587799990409
1587799994409 second step finished
1587799994409 first step finished
1587799994409 first step finished

發(fā)現(xiàn)線程1和線程2雖然都在4秒前到達await,鎖已經(jīng)解開,但是并沒有直接結(jié)束,而是等待4秒,讓優(yōu)先線程跑完,才執(zhí)行結(jié)束線程1和2.

如果我不設(shè)置優(yōu)先線程,則是這樣的

           FinalTask finalTask = new FinalTask();               
        CyclicBarrier barrier = new CyclicBarrier(2);
        new Thread(new NormalTask(barrier),"線程1").start();
        new Thread(new NormalTask(barrier),"線程2").start();
        new Thread(finalTask,"線程3").start();

執(zhí)行結(jié)果

線程1時間1587800302651
線程2時間1587800302651
1587800302652 first step finished
1587800302652 first step finished
1587800304651 second step finished

線程1,2都到達await后即解鎖,由于沒有優(yōu)先線程的存在,則1,2直接完成。

CyclicBarrier和CountDownLatch的區(qū)別

1.CyclicBarrier和CountDownLatch的區(qū)別CountDownLatch的計數(shù)器只能使用一次,而CyclicBarrier的計數(shù)器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能夠處理更為復(fù)雜的場景;
2.CyclicBarrier還提供了一些其他有用的方法,比如getNumberWaiting()方法可以獲得CyclicBarrier阻塞的線程數(shù)量,isBroken()方法用來了解阻塞的線程是否被中斷;
3.CountDownLatch允許一個或多個線程等待一組事件的產(chǎn)生,而CyclicBarrier用于等待其他線程運行到柵欄位置。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容