Java-CountDownLatch

CountDownLatch是一个线程同步辅助类。
使用这个辅助类可以让线程等待其它线程完成一组操作后才能执行,否则就一直等待。
这个类使用一个整形参数来初始化,这个整形参数代表着等待其他线程的数量,使用await()方法让线程开始等待其他线程执行完毕,每一个线程执行完毕后后调用countDown()方法,这个方法会让CountDownLatch内部的计数器减1,当计数器变为0的时候,CountDownLatch类将唤醒所有调用await()方法并进入WAITING状态线程。

示例

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* 注意,CountDownLatch 并不是用来保护共享资源同步访问的,而是用来控制并发线程等待的。
* 并且 CountDownLatch 只允许进入一次,一旦内部计数器等于0,再调用这个方法将不起作用,
* 如果还有第二次并发等待,还得创建一个新的 CountDownLatch。
*/

public class MainClass {

/**
* 当所有线程都 join() 后,开始执行。
*/
public static void main(String[] args){
// 要加入的线程要 10 个
CountDown countDown = new CountDown(10);
Thread threadConference = new Thread(countDown);
threadConference.start();

Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(new CountIndex("P-" + i, countDown));
}
// 启动10个线程
for (int i = 0; i < 10; i++) {
threads[i].start();
}

// 运行结果:
// run:10
// duration:5
// duration:3
// duration:1
// duration:9
// duration:6
// duration:6
// duration:6
// duration:8
// duration:2
// duration:4
// join:P-3--9
// join:P-8--8
// join:P-2--7
// join:P-9--6
// join:P-0--5
// join:P-4--2
// join:P-6--2
// join:P-5--2
// join:P-7--1
// join:P-1--0
// CountDown:All the CountIndex have join.
// CountDown:Let's start...
// Process finished with exit code 0

}

/**
* 声明一个 CountDownLatch 来控制线程等待。
* 线程启动后会调用 await() 方法并进入等待状态,每一个线程加入后用 join() 方法,
* 并把 CountDownLatch 中的计数器减1,当计数器等于 0 的时候线程继续执行。
*/
static class CountDown implements Runnable{
private final CountDownLatch downLatch;

public CountDown(int number){
downLatch = new CountDownLatch(number);
}

public void join(String name){
downLatch.countDown();
System.out.println("join:"+name+"--"+downLatch.getCount());
}

@Override
public void run() {
System.out.println("run:"+downLatch.getCount());
try {
downLatch.await();
System.out.printf("CountDown:All the CountIndex have join.\n");
System.out.printf("CountDown:Let's start...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

/**
* 创建线程类 CountIndex,这个类持有 CountDown 的引用,
* 启动后用一个随机休眠时间来模拟要 join() 所需的时间,
* 休眠结束后调用 join(name) 方法告诉 CountDown,线程加入并把CountDownLatch计数器减1。
*/
static class CountIndex implements Runnable{
private String name;
private CountDown countDown;

public CountIndex(String name, CountDown countDown) {
this.name = name;
this.countDown = countDown;
}

@Override
public void run() {
// 产生 0-10 的随机数
long duration = (long) (Math.random() * 10);
System.out.println("duration:"+duration);
try {
// 对Thread.sleep方法的包装
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDown.join(name);
}
}

}