Wetts's blog

Stay Hungry, Stay Foolish.

0%

Java-多线程-多个线程执行完毕后,才执行另一个线程.md

转自:https://blog.csdn.net/zzti_erlie/article/details/100047508

CountDownLatch

去掉try catch版本

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
public static void main(String[] args) throws InterruptedException {

/**
* Thread-1 在路上耗时4秒
* Thread-2 在路上耗时0秒
* Thread-0 在路上耗时4秒
* Thread-2 到达车站了
* Thread-1 到达车站了
* Thread-0 到达车站了
* 老司机,发车
*/
CountDownLatch countDownLatch = new CountDownLatch(3);
Random random = new Random();
for (int i = 0; i < 3; i++) {
new Thread(() -> {
//返回[0,5)的值
int time = random.nextInt(5);
System.out.println(Thread.currentThread().getName() + " 在路上耗时" + time + "秒");
TimeUnit.SECONDS.sleep(time);
System.out.println(Thread.currentThread().getName() + " 到达车站了");
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println("老司机,发车");
}

先来演示一下用法,可以看到所有子线程都执行完毕才会执行主线程。实现这个功能主要靠的是 CountDownLatch 的 2 个方法 await() 和 countDown()。

new 一个 CountDownLatch 时会传一个计数器的值,上面的例子为 3。调用 await() 方法时判断计数是否为 0,如果不为 0 则呈等待状态。其他线程可以调用 countDown() 方法将计数减 1,当计数减到位 0 时,则呈等待的线程继续执行。

CyclicBarrier

去掉try catch版本

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
public static void main(String[] args) {

/**
* Thread-1 在路上耗时0秒
* Thread-2 在路上耗时2秒
* Thread-1 到达车站了
* Thread-0 在路上耗时3秒
* Thread-2 到达车站了
* Thread-0 到达车站了
* 老司机,发车
*/
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, ()->{
System.out.println("老司机,发车");
});
Random random = new Random();
for (int i = 0; i < 3; i++) {
new Thread(() -> {
//返回[0,5)的值
int time = random.nextInt(5);
System.out.println(Thread.currentThread().getName() + " 在路上耗时" + time + "秒");
TimeUnit.SECONDS.sleep(time);
System.out.println(Thread.currentThread().getName() + " 到达车站了");
cyclicBarrier.await();
}).start();
}
}

CountDownLatch 的计数器只能使用一次,而 CyclicBarrier 的计数器可以使用 reset() 方法重置。挺简单的就不再演示。因为这 2 个工具类都用到了 AQS,而 AQS 的原理很长,因此在本文就不介绍 AQS 的实现了

CompletableFuture

去掉try catch版本

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
public static void main(String[] args) {
/**
* ForkJoinPool.commonPool-worker-1 在路上耗时4秒
* ForkJoinPool.commonPool-worker-2 在路上耗时3秒
* ForkJoinPool.commonPool-worker-1 到达车站了
* ForkJoinPool.commonPool-worker-2 到达车站了
* 老司机,发车
*/
Random random = new Random();
CompletableFuture future1 = CompletableFuture.runAsync(() -> {
int time = random.nextInt(5);
System.out.println(Thread.currentThread().getName() + " 在路上耗时" + time + "秒");
TimeUnit.SECONDS.sleep(random.nextInt());
System.out.println(Thread.currentThread().getName() + " 到达车站了");
});
CompletableFuture future2 = CompletableFuture.runAsync(() -> {
int time = random.nextInt(5);
System.out.println(Thread.currentThread().getName() + " 在路上耗时" + time + "秒");
TimeUnit.SECONDS.sleep(random.nextInt());
System.out.println(Thread.currentThread().getName() + " 到达车站了");
});
CompletableFuture.allOf(future1, future2).thenRun(() -> {
System.out.println("老司机,发车");
});
}