CountDownLatch和CyclicBarrier介紹

概述

JDK中提供了一些用于線程之間協(xié)同等待的工具類,CountDownLatchCyclicBarrier就是最典型的兩個線程同步輔助類。下面分別詳細介紹這兩個類绍申,以及他們之間的異同點。

CountDownLatch類

CountDownLatch顧名思義:倒計數(shù)鎖存器。沒錯凡壤,他就是一個計數(shù)器署尤,并且是倒著計數(shù)的。他的應用場景如下:

一個任務A亚侠,他需要等待其他的一些任務都執(zhí)行完畢之后它才能執(zhí)行曹体。就比如說賽跑的時候,發(fā)令員需要等待所有運動員都準備好了才能發(fā)令硝烂,否則不被K才怪嘞箕别!

此時CountDownLatch就可以大展身手了。

常用操作

本節(jié)介紹CountDownLatch的基本操作函數(shù)滞谢。

構(gòu)造函數(shù)

函數(shù)簽名如下:

public CountDownLatch(int count)

用一個給定的數(shù)值初始化CountDownLatch串稀,之后計數(shù)器就從這個值開始倒計數(shù),直到計數(shù)值達到零狮杨。

await函數(shù)

await函數(shù)用兩種形式母截,簽名分別如下:

public void await() throws InterruptedException
public boolean await(long timeout, TimeUnit unit)

這兩個函數(shù)的作用都是讓線程阻塞等待其他線程,直到CountDownLatch的計數(shù)值變?yōu)?才繼續(xù)執(zhí)行之后的操作橄教。區(qū)別在于第一個函數(shù)沒有等待時間限制清寇,可以等到天荒地老,夯さ枯石爛华烟,第二個函數(shù)給定一個等待超時時間,超過該時間就直接放棄了滓走,并且第二個函數(shù)具有返回值垦江,超時時間之內(nèi)CountDownLatch的值達到0就返回true,等待時間結(jié)束計數(shù)值都還沒達到0就返回false。這兩個操作在等待過程中如果等待的線程被中斷搅方,則會拋出InterruptedException異常比吭。

countDown函數(shù)

這個函數(shù)用來將CountDownLatch的計數(shù)值減一,函數(shù)簽名如下:

public void countDown()

需要說明的是姨涡,如果調(diào)用這個函數(shù)的時候CountDownLatch的計數(shù)值已經(jīng)為0衩藤,那么這個函數(shù)什么也不會做。

getCount函數(shù)

該函數(shù)用來獲取當前CountDownLatch的計數(shù)值涛漂,函數(shù)簽名如下:

public void countDown()

模擬實驗

理論知識講完了赏表,需要真槍實戰(zhàn)地來演示一下這個類的作用,我們就以下面這個場景為例子匈仗,用CountDownLatch來實現(xiàn)這個需求:

有5個運動員賽跑瓢剿,開跑之前,裁判需要等待5個運動員都準備好才能發(fā)令悠轩,并且5個運動員準備好之后也都需要等待裁判發(fā)令才能開跑间狂。

首先分析一下依賴關(guān)系:

裁判發(fā)令 -> 5個運動員都準備好;
5個運動員開跑 -> 裁判發(fā)令火架。

好鉴象,依賴關(guān)系已經(jīng)出來了忙菠,代碼實現(xiàn):

package com.winwill.test;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

/**
 * @author qifuguang
 * @date 15/8/24 23:35
 */
public class TestCountDownLatch {
    private static final int RUNNER_NUMBER = 5; // 運動員個數(shù)
    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        // 用于判斷發(fā)令之前運動員是否已經(jīng)完全進入準備狀態(tài),需要等待5個運動員纺弊,所以參數(shù)為5
        CountDownLatch readyLatch = new CountDownLatch(RUNNER_NUMBER);
        // 用于判斷裁判是否已經(jīng)發(fā)令牛欢,只需要等待一個裁判,所以參數(shù)為1
        CountDownLatch startLatch = new CountDownLatch(1);
        for (int i = 0; i < RUNNER_NUMBER; i++) {
            Thread t = new Thread(new Runner((i + 1) + "號運動員", readyLatch, startLatch));
            t.start();
        }
        try {
            readyLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        startLatch.countDown();
        System.out.println("裁判:所有運動員準備完畢淆游,開始...");
    }

    static class Runner implements Runnable {
        private CountDownLatch readyLatch;
        private CountDownLatch startLatch;
        private String name;

        public Runner(String name, CountDownLatch readyLatch, CountDownLatch startLatch) {
            this.name = name;
            this.readyLatch = readyLatch;
            this.startLatch = startLatch;
        }

        public void run() {
            int readyTime = RANDOM.nextInt(1000);
            System.out.println(name + ":我需要" + readyTime + "秒時間準備.");
            try {
                Thread.sleep(readyTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + ":我已經(jīng)準備完畢.");
            readyLatch.countDown();
            try {
                startLatch.await();  // 等待裁判發(fā)開始命令
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + ":開跑...");
        }
    }
}

運行結(jié)果如下:

1號運動員:我需要389秒時間準備.
2號運動員:我需要449秒時間準備.
3號運動員:我需要160秒時間準備.
4號運動員:我需要325秒時間準備.
5號運動員:我需要978秒時間準備.
3號運動員:我已經(jīng)準備完畢.
4號運動員:我已經(jīng)準備完畢.
1號運動員:我已經(jīng)準備完畢.
2號運動員:我已經(jīng)準備完畢.
5號運動員:我已經(jīng)準備完畢.
裁判:所有運動員準備完畢傍睹,開始...
1號運動員:開跑...
5號運動員:開跑...
2號運動員:開跑...
4號運動員:開跑...
3號運動員:開跑...

可以看到,一切都是如此地完美稽犁,運動員準備好了之后裁判才發(fā)令焰望,裁判發(fā)令之后運動員才開跑骚亿。

CyclicBarrier類

CyclicBarrier翻譯過來就是:循環(huán)的屏障已亥。什么是循環(huán)?可以重復利用唄来屠,對這個類就是一個可以重復利用的屏障類虑椎。CyclicBarrier主要用于一組固定大小的線程之間,各個線程之間相互等待俱笛,當所有線程都完成某項任務之后捆姜,才能執(zhí)行之后的任務。
如下場景:

有若干個線程都需要向一個數(shù)據(jù)庫寫數(shù)據(jù)迎膜,但是必須要所有的線程都講數(shù)據(jù)寫入完畢他們才能繼續(xù)做之后的事情泥技。

分析一下這個場景的特征:

  • 各個線程都必須完成某項任務(寫數(shù)據(jù))才能繼續(xù)做后續(xù)的任務;
  • 各個線程需要相互等待磕仅,不能獨善其身珊豹。

這種場景便可以利用CyclicBarrier來完美解決。

常用函數(shù)

本節(jié)介紹CyclicBarrier的基本操作函數(shù)榕订。

構(gòu)造函數(shù)

有兩種類型的構(gòu)造函數(shù)店茶,函數(shù)簽名分別如下:

public CyclicBarrier(int parties, Runnable barrierAction)
public CyclicBarrier(int parties)

參數(shù)parties表示一共有多少線程參與這次“活動”,參數(shù)barrierAction是可選的劫恒,用來指定當所有線程都完成這些必須的“神秘任務”之后需要干的事情贩幻,所以barrierAction這里的動作在一個相互等待的循環(huán)內(nèi)只會執(zhí)行一次。

getParties函數(shù)

getParties用來獲取當前的CyclicBarrier一共有多少線程參數(shù)與两嘴,函數(shù)簽名如下:

public int getParties()

返回參與“活動”的線程個數(shù)丛楚。

await函數(shù)

await函數(shù)用來執(zhí)行等待操作,有兩種類型的函數(shù)簽名:

public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit)
        throws InterruptedException,
               BrokenBarrierException,
               TimeoutException 

第一個函數(shù)是一個無參函數(shù)憔辫,第二個函數(shù)可以指定等待的超時時間趣些。它們的作用是:一直等待知道所有參與“活動”的線程都調(diào)用過await函數(shù),如果當前線程不是即將調(diào)用await函數(shù)的的最后一個線程螺垢,當前線程將會被掛起喧务,直到下列某一種情況發(fā)生:

  • 最后一個線程調(diào)用了await函數(shù)逞刷;
  • 某個線程打斷了當前線程于置;
  • 某個線程打斷了其他某個正在等待的線程;
  • 其他某個線程等待時間超過給定的超時時間;
  • 其他某個線程調(diào)用了reset函數(shù)骏全。

如果等待過程中線程被打斷了,則會拋出InterruptedException異常河绽;
如果等待過程中出現(xiàn)下列情況中的某一種情況剪芍,則會拋出BrokenBarrierException異常:

  • 其他線程被打斷了;
  • 當前線程等待超時了玲昧;
  • 當前CyclicBarrier被reset了栖茉;
  • 等待過程中CyclicBarrier損壞了;
  • 構(gòu)造函數(shù)中指定的barrierAction在執(zhí)行過程中發(fā)生了異常孵延。

如果等待時間超過給定的最大等待時間吕漂,則會拋出TimeoutException異常,并且這個時候其他已經(jīng)嗲用過await函數(shù)的線程將會繼續(xù)后續(xù)的動作尘应。

返回值:返回當前線程在調(diào)用過await函數(shù)的所以線程中的編號惶凝,編號為parties-1的表示第一個調(diào)用await函數(shù),編號為0表示是最后一個調(diào)用await函數(shù)犬钢。

isBroken函數(shù)

給函數(shù)用來判斷barrier是否已經(jīng)損壞苍鲜,函數(shù)簽名如下:

public boolean isBroken()

如果因為任何原因被損壞返回true,否則返回false玷犹。

reset函數(shù)

顧名思義混滔,這個函數(shù)用來重置barrier,函數(shù)簽名如下:

public void reset()

如果調(diào)用了該函數(shù)歹颓,則在等待的線程將會拋出BrokenBarrierException異常坯屿。

getNumberWaiting函數(shù)

該函數(shù)用來獲取當前正在等待該barrier的線程數(shù),函數(shù)簽名如下:

public int getNumberWaiting()

模擬實驗

下面用代碼實現(xiàn)下面的場景:

有5個線程都需要向一個數(shù)據(jù)庫寫數(shù)據(jù)晴股,但是必須要所有的線程都講數(shù)據(jù)寫入完畢他們才能繼續(xù)做之后的事情愿伴。

一般情況

代碼:

package com.winwill.test;

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

/**
 * @author qifuguang
 * @date 15/8/25 00:34
 */
public class TestCyclicBarrier {
    private static final int THREAD_NUMBER = 5;
    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(THREAD_NUMBER, new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getId() + ":我宣布,所有小伙伴寫入數(shù)據(jù)完畢");
            }
        });
        for (int i = 0; i < THREAD_NUMBER; i++) {
            Thread t = new Thread(new Worker(barrier));
            t.start();
        }
    }

    static class Worker implements Runnable {
        private CyclicBarrier barrier;

        public Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        public void run() {
            int time = RANDOM.nextInt(1000);
            System.out.println(Thread.currentThread().getId() + ":我需要" + time + "毫秒時間寫入數(shù)據(jù).");
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":寫入數(shù)據(jù)完畢电湘,等待其他小伙伴...");
            try {
                barrier.await(); // 等待所有線程都調(diào)用過此函數(shù)才能進行后續(xù)動作
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":所有線程都寫入數(shù)據(jù)完畢隔节,繼續(xù)干活...");
        }
    }
}

運行結(jié)果如下:

10:我需要16毫秒時間寫入數(shù)據(jù).
11:我需要353毫秒時間寫入數(shù)據(jù).
12:我需要101毫秒時間寫入數(shù)據(jù).
13:我需要744毫秒時間寫入數(shù)據(jù).
14:我需要51毫秒時間寫入數(shù)據(jù).
10:寫入數(shù)據(jù)完畢,等待其他小伙伴...
14:寫入數(shù)據(jù)完畢寂呛,等待其他小伙伴...
12:寫入數(shù)據(jù)完畢怎诫,等待其他小伙伴...
11:寫入數(shù)據(jù)完畢,等待其他小伙伴...
13:寫入數(shù)據(jù)完畢贷痪,等待其他小伙伴...
13:我宣布幻妓,所有小伙伴寫入數(shù)據(jù)完畢
13:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
10:所有線程都寫入數(shù)據(jù)完畢劫拢,繼續(xù)干活...
12:所有線程都寫入數(shù)據(jù)完畢肉津,繼續(xù)干活...
14:所有線程都寫入數(shù)據(jù)完畢强胰,繼續(xù)干活...
11:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...

可以看到妹沙,線程小伙伴們非常團結(jié)偶洋,寫完自己的數(shù)據(jù)之后都在等待其他小伙伴,所有小伙伴都完成之后才繼續(xù)后續(xù)的動作距糖。

重復使用

上面的例子并沒有體現(xiàn)CyclicBarrier可以循環(huán)使用的特點玄窝,所以有如下代碼:

package com.winwill.test;

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

/**
 * @author qifuguang
 * @date 15/8/25 00:34
 */
public class TestCyclicBarrier {
    private static final int THREAD_NUMBER = 5;
    private static final Random RANDOM = new Random();

    public static void main(String[] args) throws Exception {
        CyclicBarrier barrier = new CyclicBarrier(THREAD_NUMBER, new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getId() + ":我宣布,所有小伙伴寫入數(shù)據(jù)完畢");
            }
        });
        for (int i = 0; i < THREAD_NUMBER; i++) {
            Thread t = new Thread(new Worker(barrier));
            t.start();
        }
        Thread.sleep(10000);
        System.out.println("================barrier重用==========================");
        for (int i = 0; i < THREAD_NUMBER; i++) {
            Thread t = new Thread(new Worker(barrier));
            t.start();
        }
    }

    static class Worker implements Runnable {
        private CyclicBarrier barrier;

        public Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        public void run() {
            int time = RANDOM.nextInt(1000);
            System.out.println(Thread.currentThread().getId() + ":我需要" + time + "毫秒時間寫入數(shù)據(jù).");
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":寫入數(shù)據(jù)完畢悍引,等待其他小伙伴...");
            try {
                barrier.await(); // 等待所有線程都調(diào)用過此函數(shù)才能進行后續(xù)動作
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":所有線程都寫入數(shù)據(jù)完畢恩脂,繼續(xù)干活...");
        }
    }
}

運行結(jié)果:

10:我需要228毫秒時間寫入數(shù)據(jù).
11:我需要312毫秒時間寫入數(shù)據(jù).
12:我需要521毫秒時間寫入數(shù)據(jù).
13:我需要720毫秒時間寫入數(shù)據(jù).
14:我需要377毫秒時間寫入數(shù)據(jù).
10:寫入數(shù)據(jù)完畢,等待其他小伙伴...
11:寫入數(shù)據(jù)完畢趣斤,等待其他小伙伴...
14:寫入數(shù)據(jù)完畢俩块,等待其他小伙伴...
12:寫入數(shù)據(jù)完畢,等待其他小伙伴...
13:寫入數(shù)據(jù)完畢唬渗,等待其他小伙伴...
13:我宣布典阵,所有小伙伴寫入數(shù)據(jù)完畢
13:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
10:所有線程都寫入數(shù)據(jù)完畢镊逝,繼續(xù)干活...
11:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
14:所有線程都寫入數(shù)據(jù)完畢嫉鲸,繼續(xù)干活...
12:所有線程都寫入數(shù)據(jù)完畢撑蒜,繼續(xù)干活...
================barrier重用==========================
15:我需要212毫秒時間寫入數(shù)據(jù).
16:我需要691毫秒時間寫入數(shù)據(jù).
17:我需要530毫秒時間寫入數(shù)據(jù).
18:我需要758毫秒時間寫入數(shù)據(jù).
19:我需要604毫秒時間寫入數(shù)據(jù).
15:寫入數(shù)據(jù)完畢,等待其他小伙伴...
17:寫入數(shù)據(jù)完畢玄渗,等待其他小伙伴...
19:寫入數(shù)據(jù)完畢座菠,等待其他小伙伴...
16:寫入數(shù)據(jù)完畢,等待其他小伙伴...
18:寫入數(shù)據(jù)完畢藤树,等待其他小伙伴...
18:我宣布浴滴,所有小伙伴寫入數(shù)據(jù)完畢
18:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
15:所有線程都寫入數(shù)據(jù)完畢岁钓,繼續(xù)干活...
19:所有線程都寫入數(shù)據(jù)完畢升略,繼續(xù)干活...
16:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
17:所有線程都寫入數(shù)據(jù)完畢屡限,繼續(xù)干活...

可以看到品嚣,barrier的確是重用了。

等待超時

如果await的時候設置了一個最長等待時間钧大,并且等待超時翰撑,則會怎么樣呢?下面的例子故意讓一個線程延遲一段時間才開始寫數(shù)據(jù)啊央,這樣就會出現(xiàn)先等待的線程等待最后一個線程拋出等待超時異常的情況眶诈。

package com.winwill.test;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author qifuguang
 * @date 15/8/25 00:34
 */
public class TestCyclicBarrier {
    private static final int THREAD_NUMBER = 5;
    private static final Random RANDOM = new Random();

    public static void main(String[] args) throws Exception {
        CyclicBarrier barrier = new CyclicBarrier(THREAD_NUMBER, new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getId() + ":我宣布涨醋,所有小伙伴寫入數(shù)據(jù)完畢");
            }
        });
        for (int i = 0; i < THREAD_NUMBER; i++) {
            if (i < THREAD_NUMBER - 1) {
                Thread t = new Thread(new Worker(barrier));
                t.start();
            } else {  //最后一個線程故意延遲3s創(chuàng)建。
                Thread.sleep(3000);
                Thread t = new Thread(new Worker(barrier));
                t.start();
            }
        }
    }

    static class Worker implements Runnable {
        private CyclicBarrier barrier;

        public Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        public void run() {
            int time = RANDOM.nextInt(1000);
            System.out.println(Thread.currentThread().getId() + ":我需要" + time + "毫秒時間寫入數(shù)據(jù).");
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":寫入數(shù)據(jù)完畢逝撬,等待其他小伙伴...");
            try {
                barrier.await(2000, TimeUnit.MILLISECONDS); // 只等待2s东帅,必然會等待最后一個線程超時
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getId() + ":所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...");
        }
    }
}

運行結(jié)果:

10:我需要820毫秒時間寫入數(shù)據(jù).
11:我需要140毫秒時間寫入數(shù)據(jù).
12:我需要640毫秒時間寫入數(shù)據(jù).
13:我需要460毫秒時間寫入數(shù)據(jù).
11:寫入數(shù)據(jù)完畢球拦,等待其他小伙伴...
13:寫入數(shù)據(jù)完畢靠闭,等待其他小伙伴...
12:寫入數(shù)據(jù)完畢,等待其他小伙伴...
10:寫入數(shù)據(jù)完畢坎炼,等待其他小伙伴...
java.util.concurrent.BrokenBarrierException
12:所有線程都寫入數(shù)據(jù)完畢愧膀,繼續(xù)干活...
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
13:所有線程都寫入數(shù)據(jù)完畢,繼續(xù)干活...
11:所有線程都寫入數(shù)據(jù)完畢谣光,繼續(xù)干活...
10:所有線程都寫入數(shù)據(jù)完畢檩淋,繼續(xù)干活...
at com.winwill.test.TestCyclicBarrier$Worker.run(TestCyclicBarrier.java:52)
at java.lang.Thread.run(Thread.java:744)
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.winwill.test.TestCyclicBarrier$Worker.run(TestCyclicBarrier.java:52)
at java.lang.Thread.run(Thread.java:744)
java.util.concurrent.TimeoutException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:257)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.winwill.test.TestCyclicBarrier$Worker.run(TestCyclicBarrier.java:52)
at java.lang.Thread.run(Thread.java:744)
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.winwill.test.TestCyclicBarrier$Worker.run(TestCyclicBarrier.java:52)
at java.lang.Thread.run(Thread.java:744)
14:我需要850毫秒時間寫入數(shù)據(jù).
java.util.concurrent.BrokenBarrierException
14:寫入數(shù)據(jù)完畢,等待其他小伙伴...
14:所有線程都寫入數(shù)據(jù)完畢萄金,繼續(xù)干活...
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.winwill.test.TestCyclicBarrier$Worker.run(TestCyclicBarrier.java:52)
at java.lang.Thread.run(Thread.java:744)

可以看到蟀悦,前面四個線程等待最后一個線程超時了,這個時候他們不再等待最后這個小伙伴了氧敢,而是拋出異常并都繼續(xù)后續(xù)的動作日戈。最后這個線程屁顛屁顛地完成寫入數(shù)據(jù)操作之后也繼續(xù)了后續(xù)的動作。需要說明的是孙乖,發(fā)生了超時異常時候浙炼,還沒有完成“神秘任務”的線程在完成任務之后不會做任何等待,而是會直接執(zhí)行后續(xù)的操作唯袄。

總結(jié)

CountDownLatch和CyclicBarrier都能夠?qū)崿F(xiàn)線程之間的等待弯屈,只不過它們側(cè)重點不同:

  • CountDownLatch一般用于某個線程A等待若干個其他線程執(zhí)行完任務之后,它才執(zhí)行恋拷;
  • CyclicBarrier一般用于一組線程互相等待至某個狀態(tài)资厉,然后這一組線程再同時執(zhí)行;
  • CountDownLatch是不能夠重用的蔬顾,而CyclicBarrier是可以重用的宴偿。

聲明

本文為作者原創(chuàng),也純屬個人見解阎抒,如理解有誤酪我,請留言相告。轉(zhuǎn)載請注明出處: http://qifuguang.me/2015/08/25/[Java并發(fā)包學習五]CountDownLatch和CyclicBarrier介紹
如果你喜歡我的文章且叁,請關(guān)注我的微信訂閱號:“機智的程序猿”都哭,更多精彩,盡在其中:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市欺矫,隨后出現(xiàn)的幾起案子纱新,更是在濱河造成了極大的恐慌,老刑警劉巖穆趴,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脸爱,死亡現(xiàn)場離奇詭異,居然都是意外死亡未妹,警方通過查閱死者的電腦和手機簿废,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來络它,“玉大人族檬,你說我怎么就攤上這事』粒” “怎么了单料?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長点楼。 經(jīng)常有香客問我扫尖,道長,這世上最難降的妖魔是什么掠廓? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任换怖,我火速辦了婚禮,結(jié)果婚禮上却盘,老公的妹妹穿的比我還像新娘狰域。我一直安慰自己,他們只是感情好黄橘,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屈溉,像睡著了一般塞关。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上子巾,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天帆赢,我揣著相機與錄音,去河邊找鬼线梗。 笑死椰于,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的仪搔。 我是一名探鬼主播瘾婿,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了偏陪?” 一聲冷哼從身側(cè)響起抢呆,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笛谦,沒想到半個月后抱虐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡饥脑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年恳邀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灶轰。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡谣沸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出框往,到底是詐尸還是另有隱情鳄抒,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布椰弊,位于F島的核電站许溅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏秉版。R本人自食惡果不足惜贤重,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望清焕。 院中可真熱鬧并蝗,春花似錦、人聲如沸秸妥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粥惧。三九已至键畴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間突雪,已是汗流浹背起惕。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咏删,地道東北人惹想。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像督函,于是被迫代替她去往敵國和親嘀粱。 傳聞我的和親對象是個殘疾皇子激挪,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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