CyclicBarrier
循环栅栏,用来进行线程协作,等待线程满足某个计数,构造时设置[计数个数],每个线程执行到某个需要同步的时刻调用await()方法进行等待,当等待的线程数满足【计数个数】时,继续执行
与CountDownLatch区别是可以重复使用
CyclicBarrier的计数变为0之后,再次调用await方法计数会重新变为设置值,想要重复执行任务并等待只需要创建一个对象
将任务反复运行,并且主线程将返回得到的数据进行汇总:
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(3);
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
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
service.submit(() -> {
log.debug("task2 begin...");
sleep(2);
try {
barrier.await(); // 1-1=0
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
CountDownLatch也可以达到上述效果
private static void test1() {
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 3; i++) {
CountDownLatch latch = new CountDownLatch(2);
service.submit(() -> {
log.debug("task1 start...");
sleep(1);
latch.countDown();
});
service.submit(() -> {
log.debug("task2 start...");
sleep(2);
latch.countDown();
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("task1 task2 finish...");
}
service.shutdown();
}
CyclicBarrier注意点:
线程池中的线程数要与计数值一致,否则会有问题
如上述代码,任务1执行1s,任务2执行2s,若线程数有三个,而计数是2,则导致三个线程直接去执行两个任务1,一个任务2,当任务1时间短先执行完,返回的结果均为任务1的,而不会得到任务2的结果