CountDownLatch
JDK1.5被引入,在java.util.concurrent包下,其初始化一个数值(>=0),使用countDown将计数器数值减1,使用awit方法阻塞线程。当计数器数值为0时,解除阻塞。
常用方法:
public CountDownLatch(int count) // 构造方法:初始化计数器数量
public void await() // 阻塞线程
public boolean await(long timeout, TimeUnit unit) // 阻塞线程,但等待指定时间计数器仍然不等于0就不等了,继续执行
public void countDown() // 计数器值减1
public long getCount() // 获取当前值
例如:当前主线程要做四件事,分别是ABCD,但必须执行完ABC后才能执行D(ABC并发执行)
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3);
String[] list = new String[]{"A", "B", "C"};
for (String str : list) {
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:" + str + "执行");
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println("\nA、B、C全部执行完毕后,执行D");
}
运行结果:
CyclicBarrier
直译“循环屏障”,也是在JDK1.5被引入,在java.util.concurrent包下。
当一组线程到达一个屏障时被阻塞(await方法),直到这一组所有的线程全部到达时,屏障就会开门,所有的线程继续向下执行;此时屏障被重置,下次仍可循环使用。
常用方法
public CyclicBarrier(int parties) // 构造方法:初始化参与线程的个数
public CyclicBarrier(int parties, Runnable barrierAction) // 构造方法:初始化参与线程个数,并且在个数范围内的线程全部执行完毕后,执行Runnable中的任务
public int await() // 屏障点,计数器加1
public int await(long timeout, TimeUnit unit) // 屏障点,计数器加1,如果超出指定时间,则抛出TimeoutException
例如:ABC先执行第一阶段任务,必须三个人都执行完了,才能一起开始执行第二阶段任务
public static void main(String[] args) throws InterruptedException {
String[] list = new String[]{"A", "B", "C"};
CyclicBarrier cyclicBarrier = new CyclicBarrier(list.length, () -> {
System.out.println("\nA、B、C全部执行完第一阶段任务\n");
});
for (String str : list) {
new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("线程:" + str + "开始执行第一阶段任务");
cyclicBarrier.await();
Thread.sleep(1000);
System.out.println("线程:" + str + "开始执行第二阶段任务");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
运行结果:
总结:
- CountDownLatch等待线程完毕后执行;Cyclicbarrier等待线程执行到某个状态后再一起执行
- CountDownLatch基于AQS实现,Cyclicbarrier基于ReentrantLock实现
- CountDownLatch只能执行一次,计数器到0后结束,无法重置;Cyclicbarrier计数器到0后重置,可循环使用
- CountDownLatch调用countDown方法-1;Cyclicbarrier调用await方法+1
CountDownLatch源码分析请看我的另一篇博客: