CyclicBarrier(循环屏障)和CountDownLatch(倒计时门闩)都是Java并发包中的同步工具,但它们有一些区别:
1、计数器递减方式:
CountDownLatch: 计数器只能递减,一旦计数器归零,就无法重置。
CyclicBarrier: 计数器可以重复使用,一旦计数器归零,会触发一次屏障操作,然后计数器重新初始化。
2、等待方式:
CountDownLatch: 主线程等待所有计数器归零后再继续执行。
CyclicBarrier: 每个线程等待其他所有线程都到达屏障点后再继续执行。
3、使用场景:
CountDownLatch: 适用于一组线程等待另一组线程完成后再执行。
CyclicBarrier: 适用于多个线程相互等待,直到所有线程都到达一个公共的屏障点后再继续执行。
4、重用性:
CountDownLatch: 不能重用,一旦计数器归零,就无法再次使用。
CyclicBarrier: 可以重用,计数器归零后会自动重置。
5、计数器意义:
CountDownLatch: 计数器表示需要等待的事件数量。
CyclicBarrier: 计数器表示需要等待的线程数量。
总的来说,CountDownLatch适用于一次性等待多个线程的场景,而CyclicBarrier适用于多个线程相互等待的场景,并且CyclicBarrier可以重复使用。
具体方法
new CyclicBarrier(THREAD_COUNT)
创建了一个 CyclicBarrier
对象,其中 THREAD_COUNT
指定了参与线程的数量,即屏障点的数量。
CyclicBarrier.await()
是 CyclicBarrier 类中的一个方法,用于使当前线程等待直到所有线程都到达屏障点。
await()
方法被调用后,当前线程会被阻塞,直到所有参与的线程都调用了 await()
方法,且所有线程到达了屏障点。一旦所有线程都到达了屏障点,CyclicBarrier 将会释放所有被阻塞的线程,它们将继续执行。
await()
方法还具有返回值,该返回值表示当前线程在屏障点的索引位置。这个索引位置的范围是从 0 到 CyclicBarrier
构造函数中指定的参与线程数量减一
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
CyclicBarrier barrier = new CyclicBarrier(2, ()-> {
log.debug("task1, task2 finish...");
});
for (int i = 0; i < 3; i++) { // task1 task2 task1
service.submit(() -> {
log.debug("task1 begin...");
sleep(1);
try {
barrier.await(); // 2-1=1
log.debug("task1 await...");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
service.submit(() -> {
log.debug("task2 begin...");
sleep(2);
try {
barrier.await(); // 1-1=0
log.debug("task2 await...");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
13:13:13.893 c.TestCyclicBarrier [pool-1-thread-1] - task1 begin...
13:13:13.893 c.TestCyclicBarrier [pool-1-thread-2] - task2 begin...
13:13:15.902 c.TestCyclicBarrier [pool-1-thread-2] - task1, task2 finish...
13:13:15.902 c.TestCyclicBarrier [pool-1-thread-1] - task1 await...
13:13:15.902 c.TestCyclicBarrier [pool-1-thread-2] - task2 await...
13:13:15.902 c.TestCyclicBarrier [pool-1-thread-1] - task1 begin...
13:13:15.902 c.TestCyclicBarrier [pool-1-thread-2] - task2 begin...
13:13:17.906 c.TestCyclicBarrier [pool-1-thread-2] - task1, task2 finish...
13:13:17.906 c.TestCyclicBarrier [pool-1-thread-2] - task2 await...
13:13:17.906 c.TestCyclicBarrier [pool-1-thread-1] - task1 await...
13:13:17.906 c.TestCyclicBarrier [pool-1-thread-1] - task2 begin...
13:13:17.906 c.TestCyclicBarrier [pool-1-thread-2] - task1 begin...
13:13:19.921 c.TestCyclicBarrier [pool-1-thread-1] - task1, task2 finish...
13:13:19.921 c.TestCyclicBarrier [pool-1-thread-2] - task1 await...
13:13:19.921 c.TestCyclicBarrier [pool-1-thread-1] - task2 await...