CyclicBarrier 循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置【计数个数】。每个线程执行到某个需要“同步”的时刻调用 await() 方法进行等待,当等待的线程数满足【计数个数】时,继续执行。
@Slf4j(topic = "c.TestCyclicBarrier")
public class TestCyclicBarrier {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
CyclicBarrier barrier = new CyclicBarrier(2, () -> {
log.debug("task1 task2 finish...");
});
for (int i = 0; i < 3; i++) {
executorService.submit(() -> {
log.debug("task1 begin...");
sleep(1000);
try {
barrier.await();
log.debug("task1 end...");
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});
executorService.submit(() -> {
log.debug("task2 begin...");
sleep(2000);
try {
barrier.await();
log.debug("task2 end...");
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});
}
}
public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
输出
19:31:31.163 [pool-1-thread-1] - task1 begin...
19:31:31.163 [pool-1-thread-2] - task2 begin...
19:31:33.170 [pool-1-thread-2] - task1 task2 finish...
19:31:33.170 [pool-1-thread-2] - task2 end...
19:31:33.170 [pool-1-thread-1] - task1 end...
19:31:33.170 [pool-1-thread-2] - task1 begin...
19:31:33.170 [pool-1-thread-1] - task2 begin...
19:31:35.175 [pool-1-thread-1] - task1 task2 finish...
19:31:35.176 [pool-1-thread-1] - task2 end...
19:31:35.176 [pool-1-thread-1] - task1 begin...
19:31:35.176 [pool-1-thread-2] - task1 end...
19:31:35.176 [pool-1-thread-2] - task2 begin...
19:31:37.176 [pool-1-thread-2] - task1 task2 finish...
19:31:37.177 [pool-1-thread-2] - task2 end...
19:31:37.177 [pool-1-thread-1] - task1 end...
- task1 需等待 task2 执行结束,task1 才能结束
- CyclicBarrier 与 CountDownLatch 的主要区别在于 CyclicBarrier 是可以重用的 CyclicBarrier 可以被比喻为『人满发车』
- 线程池中的线程数与 CyclicBarrier 中的 parties(第一个参数) 的数量最好保持一致。
@Slf4j(topic = "c.TestCyclicBarrier")
public class TestCyclicBarrier {
public static void main(String[] args) {
// 线程数与 parties 数量未保持一致
ExecutorService executorService = Executors.newFixedThreadPool(3);
CyclicBarrier barrier = new CyclicBarrier(2, () -> {
log.debug("task1 task2 finish...");
});
// task1 执行时间为 1s,task2 执行时间为 2s
// 可能会出现线程1,线程2与线程3同时执行,其中线程1和线程3执行 task1,
// 线程2执行 task2。那么线程 1 和线程 3 在执行完 task1 后 CyclicBarrier
// 的计数就减为了0,然后就去调用 CyclicBarrier 中的后续任务(参数2)
for (int i = 0; i < 3; i++) {
executorService.submit(() -> {
log.debug("task1 begin...");
sleep(1000);
try {
barrier.await();
log.debug("task1 end...");
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});
executorService.submit(() -> {
log.debug("task2 begin...");
sleep(2000);
try {
barrier.await();
log.debug("task2 end...");
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});
}
}
public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
输出
19:40:04.736 [pool-1-thread-2] - task2 begin...
19:40:04.736 [pool-1-thread-3] - task1 begin...
19:40:04.736 [pool-1-thread-1] - task1 begin...
19:40:05.742 [pool-1-thread-1] - task1 task2 finish...
19:40:05.742 [pool-1-thread-1] - task1 end...
19:40:05.743 [pool-1-thread-3] - task1 end...
19:40:05.743 [pool-1-thread-1] - task2 begin...
19:40:05.743 [pool-1-thread-3] - task1 begin...
19:40:06.748 [pool-1-thread-3] - task1 task2 finish...
19:40:06.748 [pool-1-thread-3] - task1 end...
19:40:06.748 [pool-1-thread-3] - task2 begin...
19:40:06.748 [pool-1-thread-2] - task2 end...
19:40:08.752 [pool-1-thread-3] - task1 task2 finish...
19:40:08.753 [pool-1-thread-3] - task2 end...
19:40:08.753 [pool-1-thread-1] - task2 end...