主要区别
- CountDownLatch:所有子线程完成后,再执行主线程
- CyclicBarrier: 所有子线程就绪后,再执行子线程
CountDownLatch
所有子线程完成后,再执行主线程
多线程 ThreadPoolTaskExecutor 应用
SpringBoot 下载文件
CyclicBarrier
有若干个线程,比如说有五个线程,需要它们都到达了某一个点之后才能开始一起执行,也就是说假如其中只有四个线程到达了这个点,还差一个线程没到达,此时这四个线程都会进入等待状态,直到第五个线程也到达了这个点之后,这五个线程才开始一起进行执行状态
所有子线程就绪后,再执行子线程
所有子线程都已经到达屏障之后,此时屏障就会消失,所有子线程继续执行,若存子线程尚未到达屏障,其他到达了屏障的线程都会进行等待
CyclicBarrier对于涉及到固定大小的线程是非常有用的,线程们必须相互等待。该屏障称之为循环屏障,是因为当等待屏障的线程被释放之后,该屏障能循环使用
package com.concurrency2;import java.util.Random;import java.util.concurrent.CyclicBarrier;public class MyTest1 { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(3); for(int i = 0;i { try { Thread.sleep((long)(Math.random() * 2000)); int randomInt = new Random().nextInt(500); System.out.println("hello " + randomInt); cyclicBarrier.await(); System.out.println("world " + randomInt); } catch (Exception e) { e.printStackTrace(); } }).start(); } }}
输出
hello 30hello 471hello 343world 343world 471world 30
重要成员变量
// 可以理解为初始化时 需要阻塞的任务个数private final int parties;// 剩余需要等待的任务个数,初始值为parties,直到为0时依次唤醒所有被阻塞的任务线程。private int count;// 每次对“栅栏”的主要成员变量进行变更操作,都应该加锁private final ReentrantLock lock = new ReentrantLock();// 用于阻塞和唤醒任务线程private final Condition trip = lock.newCondition();// 在所有线程被唤醒前,需要执行的一个Runable对应的run方法private final Runnable barrierCommand;// 用于表示“栅栏”当前的状态private Generation generation = new Generation();