CountdownLatch Example

J.U.C包同步工具类: CountdownLatch演示

直接上代码

我们用了2个CountdownLatch。主锁要求一个参与者。
另一个参与者个数与任务线程个数相同。
任务本身是带有返回值的,通过future.get获取

思路:
主线程创建10个任务,提交到线程池,线程池会立刻执行。
但是由于主锁,所有任务线程都会等待。
此时主线程先获取future对象集合。之后解锁。等待另一锁
10个任务分别执行 - 执行速度和先后顺序不定
每个任务结束,将任务锁减一,主线程此时已经确定所有子任务执行完毕
直接循环future.get() 一定是不需要等待直接拿到任务结果
主线程进行汇总处理
结束

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
// 主调线程
public class CountdownLatchTest {
public static void main(String[] args) throws Exception {
int workerSize = 10;
CountDownLatch mainLatch = new CountDownLatch(1);
CountDownLatch workerLatch = new CountDownLatch(5);
ExecutorService pool = Executors.newFixedThreadPool(workerSize);
List<Future<String>> futures = new ArrayList<Future<String>>();
for (int i = 0; i < workerSize; i++) {
Future<String> future = pool.submit(new SumWorker(mainLatch, workerLatch, i * 10));
futures.add(future);
}
mainLatch.countDown();
workerLatch.await();
pool.shutdown();
Integer total = 0;
for (Future<String> f : futures) {
String oneResult = f.get();
System.out.println(oneResult);
total += Integer.parseInt(oneResult.split(",")[1]);
}
String text = "";
int mainSum = 0;
for (int i = 0; i < 10 * workerSize; i++) {
mainSum += i;
}
System.out.println(String.format(text, workerSize, total, mainSum));
}
}
// 子任务实际上是一个求和工作
public class SumWorker implements Callable<String> {
private CountDownLatch mainLatch;
private CountDownLatch workerLatch;
private Integer startNumber;
private Integer size = 10;
public SumWorker(CountDownLatch mainLatch, CountDownLatch workerLatch, Integer startNumber) {
this.mainLatch = mainLatch;
this.workerLatch = workerLatch;
this.startNumber = startNumber;
}
@Override
public String call() throws Exception {
mainLatch.await(); // 等待主线程倒计时结束
Integer sum = 0;
for (int i = startNumber; i < startNumber + size; i++) {
sum += i;
}
String desc = Thread.currentThread().getName() + "," + sum;
workerLatch.countDown();
return desc;
}
}