转自: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("老司机,发车"); }); }
|