CountDownLatch是什么莲组?
CountDownLatch是在java1.5被引入的,跟它一起被引入的并發(fā)工具類還有CyclicBarrier、Semaphore徙缴、ConcurrentHashMap和BlockingQueue;
它們都存在于java.util.concurrent包下冒黑。
CountDownLatch能做什么田绑?
CountDownLatch這個(gè)類能夠使一個(gè)線程等待其他線程完成各自的工作后再執(zhí)行。
public class CountDownLatchSample {
/**
* 計(jì)數(shù)器抡爹,用來控制線程
* 傳入?yún)?shù)2掩驱,表示計(jì)數(shù)器計(jì)數(shù)為2
*/
private final static CountDownLatch mCountDownLatch = new CountDownLatch(2);
/**
* 示例工作線程類
*/
private static class WorkingThread extends Thread {
private final String mThreadName;
private final int mSleepTime;
public WorkingThread(String name, int sleepTime) {
mThreadName = name;
mSleepTime = sleepTime;
}
@Override
public void run() {
System.out.println("[" + mThreadName + "] started!");
try {
Thread.sleep(mSleepTime);
// 執(zhí)行一次 count 減一
mCountDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + mThreadName + "] end!");
}
}
/**
* 示例線程類
*/
private static class SampleThread extends Thread {
@Override
public void run() {
try {
System.out.println("主線程開始等待");
// 會(huì)在這里堵塞,直到 count 為0 或者超時(shí)時(shí)間達(dá)到4秒
mCountDownLatch.await(4000, TimeUnit.MILLISECONDS);
System.out.println("主線程結(jié)束等待");
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args) throws Exception {
// 最先run SampleThread
new SampleThread().start();
// 運(yùn)行兩個(gè)工作線程
// 工作線程1運(yùn)行5秒
new WorkingThread("線程一", 5000).start();
// 工作線程2運(yùn)行2秒
new WorkingThread("線程二", 2000).start();
}
}
CountDownLatch內(nèi)部如何實(shí)現(xiàn)的冬竟?
CountDownLatch是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的欧穴,計(jì)數(shù)器的初始值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后泵殴,計(jì)數(shù)器的值就會(huì)減1涮帘。當(dāng)計(jì)數(shù)器值到達(dá)0時(shí),它表示所有的線程已經(jīng)完成了任務(wù)笑诅,然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)调缨。
構(gòu)造器中的計(jì)數(shù)值(count)實(shí)際上就是閉鎖需要等待的線程數(shù)量疮鲫。這個(gè)值只能被設(shè)置一次,而且CountDownLatch沒有提供任何機(jī)制去重新設(shè)置這個(gè)計(jì)數(shù)值弦叶。
與CountDownLatch的第一次交互是主線程等待其他線程俊犯。主線程必須在啟動(dòng)其他線程后立即調(diào)用CountDownLatch.await()方法。這樣主線程的操作就會(huì)在這個(gè)方法上阻塞湾蔓,直到其他線程完成各自的任務(wù)瘫析。
其他N 個(gè)線程必須引用閉鎖對(duì)象,因?yàn)樗麄冃枰ㄖ狢ountDownLatch對(duì)象默责,他們已經(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ù)。