初識CountDownLatch

初識CountDownLatch

標(biāo)簽:并發(fā)


原文鏈接:初識CountDownLatch 轉(zhuǎn)載請注明出處~

CountDownLatch是什么

在java.util.concurrent包內(nèi)。CountDownLatch是一個(gè)同步工具類角虫,允許一個(gè)或多個(gè)線程一直等待拙毫,直等到其他線程的某些操作執(zhí)行完成后再繼續(xù)執(zhí)行卵凑。

CountDownLatch是在java1.5被引入的叫挟,跟它一起被引入的并發(fā)工具類還有CyclicBarrier双炕、Semaphore踱蠢、ConcurrentHashMap和BlockingQueue袖肥,它們都存在于java.util.concurrent包下咪辱。CountDownLatch這個(gè)類能夠使一個(gè)線程等待其他線程完成各自的工作后再執(zhí)行

CountDownLatch如何工作

CountDownLatch是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始值為線程的數(shù)量椎组。每當(dāng)一個(gè)線程完成了自己的任務(wù)后油狂,計(jì)數(shù)器的值就會減1。當(dāng)計(jì)數(shù)器值到達(dá)0時(shí)寸癌,它表示所有的線程已經(jīng)完成了任務(wù)专筷,然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)。

CountDownLatch偽代碼

//Main thread start
//Create CountDownLatch for N threads
//Create and start N threads
//Main thread wait on latch
//N threads completes there tasks are returns
//Main thread resume execution

CountDownLatch.java類中定義的構(gòu)造函數(shù):

//Constructs a CountDownLatch initialized with the given count.
public void CountDownLatch(int count) {...}

構(gòu)造器中的計(jì)數(shù)器(count)是實(shí)際上閉鎖需要等待的線程數(shù)量蒸苇。這個(gè)值只能被設(shè)置一次磷蛹,CountDownLatch沒有提供任何機(jī)制去重新設(shè)置這個(gè)值

與CountDownLatch的第一次交互是主線程等待其他線程,主線程必須在啟動其他線程后立即調(diào)用CountDownLatch.await()方法填渠。這樣主線程的操作會在這個(gè)方法上阻塞弦聂,直到其他線程完成各自的任務(wù)鸟辅。

其他N個(gè)線程必須引用閉鎖對象氛什,因?yàn)樗麄冃枰ㄖ狢ountDownLatch對象莺葫,他們已經(jīng)完成了各自的任務(wù)。這種通知機(jī)制是通過 CountDownLatch.countDown()方法來完成的枪眉;每調(diào)用一次這個(gè)方法捺檬,在構(gòu)造函數(shù)中初始化的count值就減1。所以當(dāng)N個(gè)線程都調(diào) 用了這個(gè)方法贸铜,count的值等于0堡纬,然后主線程就能通過await()方法,恢復(fù)執(zhí)行自己的任務(wù)蒿秦。

主要方法

// Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted.
void    await() 

// Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses.
boolean await(long timeout, TimeUnit unit)

void    countDown()
Decrements the count of the latch, releasing all waiting threads if the count reaches zero.

long    getCount()
Returns the current count.

String  toString()
Returns a string identifying this latch, as well as its state.

一個(gè)例子

在這個(gè)例子中烤镐,我模擬了一個(gè)應(yīng)用程序啟動類,它開始時(shí)啟動了n個(gè)線程類棍鳖,這些線程將檢查外部系統(tǒng)并通知閉鎖炮叶,并且啟動類一直在閉鎖上等待著。一旦驗(yàn)證和檢查了所有外部服務(wù)渡处,那么啟動類恢復(fù)執(zhí)行镜悉。

BaseHealthChecker.java:這個(gè)類是一個(gè)Runnable,負(fù)責(zé)所有特定的外部服務(wù)健康的檢測医瘫。它刪除了重復(fù)的代碼和閉鎖的中心控制代碼侣肄。

public abstract class BaseHealthChecker implements Runnable {
 
    private CountDownLatch _latch;
    private String _serviceName;
    private boolean _serviceUp;
 
    //Get latch object in constructor so that after completing the task, thread can countDown() the latch
    public BaseHealthChecker(String serviceName, CountDownLatch latch)
    {
        super();
        this._latch = latch;
        this._serviceName = serviceName;
        this._serviceUp = true;
    }
 
    @Override
    public void run() {
        try {
            verifyService();
            _serviceUp = true;
        } catch (Throwable t) {
            t.printStackTrace(System.err);
            _serviceUp = false;
        } finally {
            if(_latch != null) {
                _latch.countDown();
            }
        }
    }
 
    public String getServiceName() {
        return _serviceName;
    }
 
    public boolean isServiceUp() {
        return _serviceUp;
    }
    //This methos needs to be implemented by all specific service checker
    public abstract void verifyService();
}

NetworkHealthChecker.java:這個(gè)類繼承了BaseHealthChecker,實(shí)現(xiàn)了verifyService()方法醇份。DatabaseHealthChecker.java和CacheHealthChecker.java除了服務(wù)名和休眠時(shí)間外稼锅,與NetworkHealthChecker.java是一樣的。

public class NetworkHealthChecker extends BaseHealthChecker
{
    public NetworkHealthChecker (CountDownLatch latch)  {
        super("Network Service", latch);
    }
 
    @Override
    public void verifyService()
    {
        System.out.println("Checking " + this.getServiceName());
        try
        {
            Thread.sleep(7000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println(this.getServiceName() + " is UP");
    }
}

ApplicationStartupUtil.java:這個(gè)類是一個(gè)主啟動類僚纷,它負(fù)責(zé)初始化閉鎖缰贝,然后等待,直到所有服務(wù)都被檢測完畔濒。

public class ApplicationStartupUtil
{
    //List of service checkers
    private static List<BaseHealthChecker> _services;
 
    //This latch will be used to wait on
    private static CountDownLatch _latch;
 
    private ApplicationStartupUtil()
    {
    }
 
    private final static ApplicationStartupUtil INSTANCE = new ApplicationStartupUtil();
 
    public static ApplicationStartupUtil getInstance()
    {
        return INSTANCE;
    }
 
    public static boolean checkExternalServices() throws Exception
    {
        //Initialize the latch with number of service checkers
        _latch = new CountDownLatch(3);
 
        //All add checker in lists
        _services = new ArrayList<BaseHealthChecker>();
        _services.add(new NetworkHealthChecker(_latch));
        _services.add(new CacheHealthChecker(_latch));
        _services.add(new DatabaseHealthChecker(_latch));
 
        //Start service checkers using executor framework
        Executor executor = Executors.newFixedThreadPool(_services.size());
 
        for(final BaseHealthChecker v : _services)
        {
            executor.execute(v);
        }
 
        //Now wait till all services are checked
        _latch.await();
 
        //Services are file and now proceed startup
        for(final BaseHealthChecker v : _services)
        {
            if( ! v.isServiceUp())
            {
                return false;
            }
        }
        return true;
    }
}

現(xiàn)在你可以寫測試代碼去檢測一下閉鎖的功能了剩晴。

public class Main {
    public static void main(String[] args)
    {
        boolean result = false;
        try {
            result = ApplicationStartupUtil.checkExternalServices();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("External services validation completed !! Result was :: "+ result);
    }
}
Output in console:
 
Checking Network Service
Checking Cache Service
Checking Database Service
Database Service is UP
Cache Service is UP
Network Service is UP
External services validation completed !! Result was :: true

參考文獻(xiàn)

什么時(shí)候使用CountDownLatch

That's all,enjoy it~歡迎訪問博主個(gè)人博客:http://kongdehui.com/ ~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侵状,一起剝皮案震驚了整個(gè)濱河市赞弥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趣兄,老刑警劉巖绽左,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異艇潭,居然都是意外死亡拼窥,警方通過查閱死者的電腦和手機(jī)戏蔑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲁纠,“玉大人总棵,你說我怎么就攤上這事「暮” “怎么了情龄?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長捍壤。 經(jīng)常有香客問我骤视,道長,這世上最難降的妖魔是什么鹃觉? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任专酗,我火速辦了婚禮,結(jié)果婚禮上盗扇,老公的妹妹穿的比我還像新娘祷肯。我一直安慰自己,他們只是感情好粱玲,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布躬柬。 她就那樣靜靜地躺著,像睡著了一般抽减。 火紅的嫁衣襯著肌膚如雪允青。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天卵沉,我揣著相機(jī)與錄音颠锉,去河邊找鬼。 笑死史汗,一個(gè)胖子當(dāng)著我的面吹牛琼掠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播停撞,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼瓷蛙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了戈毒?” 一聲冷哼從身側(cè)響起艰猬,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎埋市,沒想到半個(gè)月后冠桃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡道宅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年食听,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胸蛛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡樱报,死狀恐怖葬项,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肃弟,我是刑警寧澤玷室,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布零蓉,位于F島的核電站笤受,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏敌蜂。R本人自食惡果不足惜箩兽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望章喉。 院中可真熱鬧汗贫,春花似錦、人聲如沸秸脱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摊唇。三九已至咐蝇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巷查,已是汗流浹背有序。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岛请,地道東北人旭寿。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓期贫,卻偏偏與公主長得像序目,于是被迫代替她去往敵國和親朴沿。 傳聞我的和親對象是個(gè)殘疾皇子理茎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 譯序 本指南根據(jù) Jakob Jenkov 最新博客翻譯泡徙,請隨時(shí)關(guān)注博客更新:http://tutorials.j...
    高廣超閱讀 5,079評論 1 68
  • 一.線程安全性 線程安全是建立在對于對象狀態(tài)訪問操作進(jìn)行管理雨让,特別是對共享的與可變的狀態(tài)的訪問 解釋下上面的話: ...
    黃大大吃不胖閱讀 828評論 0 3
  • 喜歡 不喜歡 這些都不重要 無論別人怎么說 自己的感受才最真實(shí) 不用在意別人怎么看 保持自己的態(tài)度 無論對事霎苗、對人...
    葉子青書閱讀 150評論 0 1
  • 【小花涵涵】學(xué)習(xí)力四期踐行D40 2017-01-02 今天一大早上課去了循狰,爸爸姥姥陪寶貝玩一天咧擂,下課回來跟我說:...
    夏蘇的花園閱讀 229評論 0 0
  • 那些改革開放初期致富成功的人逞盆,就是因?yàn)檎袅颂摌s面具,才走上了成功之路松申。許多富豪都是從“破爛王”和“臭皮匠”干起而...
    贏世界運(yùn)營閱讀 463評論 0 0