countdownlatch

前言: 一个使用场景,例如分发10个线程,需要等到这10个线程全部都执行完毕后,再进行下一步的处理。

看到过一个例子:举行跑步比赛,发令枪响后,几位选手开始跑步,当最后一位选手跑完全程,然后开始公布选手成绩、以及颁奖仪式。

  1. 模拟多个线程同时执行的场景
  2. 模拟依赖场景,例如一个数据的计算需要很多数据来源,需要这些数据来源全部加载完毕后才开始进行计算。

主要方法

  1. int getCount
  2. await()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class LatchTest {

private static final Logger LOGGER = Logger.getLogger("LatchTest");

@Test
public void test() {

CountDownLatch latch = new CountDownLatch(1);

for (int i = 0; i < 10; i++) {
new Thread(deal(i, latch)).start();
}

LOGGER.info("3秒后开始....");
SleepUtil.sleep(3000);
latch.countDown();
}

private Runnable deal(int threadNum, CountDownLatch latch) {

return new Runnable() {
@Override
public void run() {

try {
latch.await();

LOGGER.info("开始运行...");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
};
}

@Test
public void test2() {
CountDownLatch latch = new CountDownLatch(10);

for (int i = 0; i < 10; i++) {
new Thread(deal2(i, latch)).start();
}

LOGGER.info("等待加载中...");
try {
latch.await();

LOGGER.info("开始进入主界面");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private Runnable deal2(int threadNum, CountDownLatch latch) {

return new Runnable() {
@Override
public void run() {

try {
LOGGER.info(threadNum + "开始运行");
SleepUtil.sleep(1000);
LOGGER.info(threadNum + "运行结束");
} catch (Exception e) {
} finally {
latch.countDown(); // 放在finally语句块中,无论程序正常执行还是出现异常,都会执行
}
}
};
}
}

Reference