CyclicBarrier
字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态(屏障点)之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
//可以进行汇总业务逻辑处理
System.out.println("5个任务线程都到达了终点");
});
for (int i = 0; i < 20; i++) {
new Thread(() -> {
try {
Thread.sleep(new Random().nextInt(2000));
System.out.println("线程" + Thread.currentThread().getName() + "准备好了");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
执行结果:
线程Thread-14准备好了
线程Thread-8准备好了
线程Thread-3准备好了
线程Thread-7准备好了
线程Thread-0准备好了
5个任务线程都到达了终点
线程Thread-16准备好了
线程Thread-11准备好了
线程Thread-12准备好了
线程Thread-9准备好了
线程Thread-19准备好了
5个任务线程都到达了终点
线程Thread-4准备好了
线程Thread-2准备好了
线程Thread-5准备好了
线程Thread-13准备好了
线程Thread-1准备好了
5个任务线程都到达了终点
线程Thread-18准备好了
线程Thread-17准备好了
线程Thread-15准备好了
线程Thread-6准备好了
线程Thread-10准备好了
5个任务线程都到达了终点
CyclicBarrier与countDownLatch区别
- CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()
方法重置。所以CyclicBarrier能处理更为复杂的业务场景,比如如果计算发生错误,可
以重置计数器,并让线程们重新执行一次
- CyclicBarrier还提供getNumberWaiting(可以获得CyclicBarrier阻塞的线程数量)、
isBroken(用来知道阻塞的线程是否被中断)等方法。
-
CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。
-
CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点
不同。CountDownLatch一般用于一个或多个线程,等待其他线程执行完任务后,再执
行。CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执
行。
-
CyclicBarrier 还可以提供一个 barrierAction,合并多线程计算结果。
-
CyclicBarrier是通过ReentrantLock的"独占锁"和Conditon来实现一组线程的阻塞
唤醒的,而CountDownLatch则是通过AQS的“共享锁”实现