CountDownLatch与CyclicBarrier区别
CountDownLatch
JUC包下的并发工具类CountDownLatch,CountDownLatch为递减计数器,用于控制一个线
程等待多个线程。维护一个计数器count,表示需要等待的事件数量,countdown方法递减计数
器,表示事件发生,调用await()方法的线程会一直阻塞直到计数器为零,或者等待中的线程中断,
或者等待超时
CyclicBarrier
CyclicBarrier,循环栅栏可以让一组线程等待至某个状态之后再全部同时执行,之所以叫循环是因
为所有等待线程被释放后可以调用reset()方法重用。两个比较重要的方法是await()和await(time),构造方法CyclicBarrier(int, Runnable)可以让所有线程到达栅栏状态是优先执行此动作。和CountDownLatch最重要的区别就是countdown()方法后会继续执行自己的任务,而CyclicBarrier会在所有线程任务到达栅栏处才执行后续任务
区别
CountDownLatch 是计数器,只能使用一次,而 CyclicBarrier 的计数器提供 reset() 功能,可以多次使用
对于 CountDownLatch 来说,重点是“一个线程(多个线程)等待”,而其他的 N 个线程在完成“某件事情”之后,可以终止,也可以等待。而对于 CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须等待
CountDownLatch 是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而 CyclicBarrier 更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行
CountDownLatch :计数器,设置一个值,通过countDown 将数量减1,一直减到0,
在执行 await() 等待所有异步线程执行完毕再向下执行
@GetMapping("/test1")
public void test1() throws InterruptedException {
long l = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(2);
AtomicInteger a = new AtomicInteger();
AtomicInteger b = new AtomicInteger();
new Thread(()->{
try {
a.set(test.a());
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"a").start();
new Thread(()->{
try {
b.set(test.b());
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"b").start();
countDownLatch.await();
System.out.println(a.get()+b.get());
System.out.println(System.currentTimeMillis()-l);
}
@Service
public class Test {
public int a() throws InterruptedException {
System.out.println("a");
Thread.sleep(1000);
return 1;
}
public int b() throws InterruptedException {
System.out.println("b");
Thread.sleep(1000);
return 2;
}
}
CyclicBarrier 反向操作,循环阻塞,设置一个值,每个程序执行阻塞数+1,
加到目标值后执行 await()之后的业务
@GetMapping("/test1")
public void test1() throws InterruptedException {
long l = System.currentTimeMillis();
AtomicInteger a = new AtomicInteger();
AtomicInteger b = new AtomicInteger();
CyclicBarrier cyclicBarrier = new CyclicBarrier(2,()->{
System.out.println(a.get()+b.get());
System.out.println(System.currentTimeMillis()-l);
});
new Thread(()->{
try {
a.set(test.a());
cyclicBarrier.await();
} catch (BrokenBarrierException | InterruptedException e) {
e.printStackTrace();
}
},"a").start();
new Thread(()->{
try {
b.set(test.b());
cyclicBarrier.await();
} catch (BrokenBarrierException | InterruptedException e) {
e.printStackTrace();
}
},"b").start();
}
使用场景:
导出用户账单明细,按年月日三个维度进行计算并显示,年月日分别放入 3 个 Excel 中,
最终将Excel 合并为一个 zip 压缩文件返回给用户