背景介绍

CylicBarrier是用于一组线程全部到达共同屏障点的同步辅助,可用于大任务拆分小任务。例如:根据10个组织code查询人,然后将这10个组织中的人取交集,此时可以启动10个线程,分别传入组织code查询单个组织下的人,等这10个线程执行完成后对这些返回的人员列表取交集

  1. public class CyclicBarrierTest {
  2. @Test
  3. public void testCyclicBarrier() throws InterruptedException {
  4. CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("任务都执行完了,开始继续执行"));
  5. new Thread(() -> {
  6. try {
  7. System.out.println("线程1执行完成");
  8. cyclicBarrier.await();
  9. System.out.println("线程1退出");
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }).start();
  14. new Thread(() -> {
  15. try {
  16. System.out.println("线程2执行完成");
  17. cyclicBarrier.await();
  18. System.out.println("线程2退出");
  19. } catch (Exception e) {
  20. e.printStackTrace();
  21. }
  22. }).start();
  23. }
  24. }

原理

核心变量分析

截屏2021-01-20 下午3.35.19.png

初始化

当我们调用CyclicBarrier的构造方法时,就是初始化count参数和command参数。parties参数记录了初始值,后续重置计数器的时候会用到

  1. CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("任务都执行完了,开始继续执行"));

截屏2021-01-20 下午3.47.35.png

await

在线程调用await方法之后会通过ReentrantLock尝试获取锁,获取到锁后对count进行-1操作,如果此时count不等于0,则通过Condition的await方法释放锁资源并进入等待队列。如果此时count等于0,则执行command中的run方法,并唤醒所有await中的方法,然后重置计数器
截屏2021-01-20 下午4.12.53.png