定义
CyclicBarrier:Cyclic(循环),Barrier(屏障)。循环屏障或者循环栅栏,它的功能就是,让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会打开,此时被阻塞的线程就会继续执行。当线程调用CyclicBarrier的await()方法后,相当于告诉CyclicBarrier我到达了屏障,然后当前线程就会被阻塞。
应用场景
CyclicBarrier可以用于多个线程计算结果,最后合并计算结果的场景。
代码清单
CyclicBarrier的定义为3,即当有3个线程到达屏障时,就会打开屏障,让这三个线程继续往下执行。
package com.mark.learning.concurrent2.flowcontrol.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo1 {
/** 定义CyclicBarrier,屏障大小为3 **/
private static final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("所有线程都到齐了,统一出发");
}
});
public static void main(String[] args) {
//声明一个固定大小的线程池,线程容量为5
ExecutorService executorService = Executors.newFixedThreadPool(5);
//执行10个子任务
for (int i = 0; i < 10; i++) {
executorService.execute(new Task(cyclicBarrier));
}
executorService.shutdown();
}
private static class Task implements Runnable {
private CyclicBarrier cyclicBarrier;
private Task(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "到达了集合地点,正在等待其他线程");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + "出发!");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
运行结果
实例中屏障的大小为3,任务数量为10。3个任务为一组依次通过屏障,那么最后有一个任务被阻塞住,因为没有多余的两个线程到达屏障了。
CyclicBarrier和CountDownLath的区别
- 作用不用:CyclicBarrier需要等待一定数量的线程到达屏障后,这些线程才能继续执行,显而易见CyclicBarrier面向的是线程。CountDownLath是等待计数为0时,而计数减一这个操作不定义是有由一个线程执行了,可以在一个线程中进行多次减一,CountDownLath面向的事件。
- 可重用性不同:CountDownLath在倒数到0时,门闩打开后就不能再次使用了。而CyclicBarrier可以复用。