- 引入CountDownLatch類
- CountDownLatch類的具體實例
- CountDownLatch小結(jié)
引入CountDownLatch類
Java在JDK1.5之后引入了CountDownLatch類郑气。這個類是一個同步輔助類栗竖。用于一個線程等待多個操作完成之后再執(zhí)行,也就是這個當(dāng)前線程會一直阻塞回懦,直到它所等待的多個操作已經(jīng)完成态贤。首先CountDownLatch類會初始化舱呻,設(shè)置它需要等待完成的操作的數(shù)量。然后每當(dāng)一個操作完成之后悠汽,就會調(diào)用countDown方法箱吕,這個方法會將CountDownLatch內(nèi)部的計數(shù)器減一。當(dāng)減為0的時候柿冲,CountDownLatch類會喚醒所有調(diào)用await方法而進(jìn)入休眠的線程茬高。
CountDownLatch類的具體實例
多說無意,我們具體看一個實例就可以理解CountDownLatch類的使用了假抄。
我們舉一個最直觀的例子怎栽,比如我們需要開一個視頻會議,這個會議需要等待一定的人數(shù)到達(dá)之后慨亲,才開始會議婚瓜。這種情況就非常適合使用CountDownLatch類來進(jìn)行同步,也就是等待多個并發(fā)事件的發(fā)生刑棵,因為每個參會人員的到達(dá)是并發(fā)的巴刻。
首先我們實現(xiàn)會議類,這個類持有一個CountDownLatch類的對象蛉签,并且定義了一個arrive方法胡陪,每當(dāng)會議人員到達(dá)之后沥寥,就會調(diào)用這個方法,告訴會議已經(jīng)到達(dá)了柠座,這個方法邑雅,會調(diào)用CountDown方法,將計數(shù)器減一妈经。
在會議類的run方法中淮野,在宣布會議開始之前,會調(diào)用CountDownLatch類的await方法休眠吹泡,直到countDown減為0骤星,也就是計數(shù)器減為0,說明所有的人都到了爆哑,才喚醒繼續(xù)這個線程的代碼洞难,宣布會議開始
package CountDown;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class VideoConference implements Runnable {
private final CountDownLatch controller;
public VideoConference(int number) {
controller = new CountDownLatch(10);
}
public synchronized void arrive(String name) {
System.out.println(name + " has arrived.");
System.out.println("VideoConference : waiting for " + (controller.getCount() - 1) + " partivipants");
controller.countDown();
}
@Override
public void run() {
System.out.println("VideoConference : Innitiaization : " + controller.getCount() + " participants");
try {
controller.await();
System.out.println("All people has come");
System.out.println("Let's start...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
接著我們實現(xiàn)參會人員的類,這個類也實現(xiàn)了runnable接口揭朝,首先它持有一個會議對象队贱,為了在執(zhí)行的時候調(diào)用arrive方法,告訴會議人員到了潭袱。
package CountDown;
import java.util.concurrent.TimeUnit;
public class Participant implements Runnable {
private VideoConference conference;
private String name;
public Participant(VideoConference conference, String name) {
this.conference = conference;
this.name = name;
}
@Override
public void run() {
long duration = (long)Math.random() * 10;
try {
TimeUnit.SECONDS.sleep(duration + 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
conference.arrive(name);
}
}
最后我們實現(xiàn)測試類
package CountDown;
public class Main {
public static void main(String[] args) {
VideoConference conference = new VideoConference(10);
new Thread(conference).start();
for(int i=0;i<10;i++) {
Participant p = new Participant(conference, "Participant " + i);
new Thread(p).start();
}
}
}
運行結(jié)果:
await方法還可以指定休眠的時間柱嫌,當(dāng)休眠時間到了或者計數(shù)器減為0,就會喚醒所有被CountDownLatch休眠的線程敌卓,那我們在這里就可以使用這個休眠時間來設(shè)置慎式,我們只等10s中伶氢,如果10s中趟径,還有人沒到,我們也不管了癣防,先開始會議蜗巧。
只需對run方法進(jìn)行簡單的修改:
@Override
public void run() {
System.out.println("VideoConference : Innitiaization : " + controller.getCount() + " participants");
try {
controller.await(10, TimeUnit.SECONDS);
if(controller.getCount() == 0) {
System.out.println("All people has come");
System.out.println("Let's start...");
}
else {
System.out.println("不等了");
System.out.println("Let's start...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
運行結(jié)果
CountDownLatch小結(jié)
CountDownLatch有三個基本的要素:
一個初始值,定義必須等待多少個并發(fā)線程完成的數(shù)目
await方法蕾盯,需要等到其他操作先完成的那個線程調(diào)用的幕屹,先將線程休眠,直到其他操作完成级遭,計數(shù)器減為0望拖,才會喚醒因此休眠的線程
countDown方法,每個被等待的事件在完成之后調(diào)用挫鸽,會將計數(shù)器減一
CountDownLatch不是用來保護(hù)臨界區(qū)和共享資源的说敏,是用來同步執(zhí)行線程和操作的
CountDownLatch是一次性的,當(dāng)計數(shù)器減為0 之后丢郊,這個類就相當(dāng)于沒用盔沫,我們之后對它的操作都不起作用医咨,需要新建一個countDownLatch類