1、什么是CyclicBarrier
CyclicBarrier是一个同步屏障,它允许多个线程相互等待,直到到达某个公共屏障点,才能继续执行。也就是说它的作用就是会让所有线程都等待完成后才会继续下一步行动。
举个简单的例子就是在学校参加会议时,有的同学早到,有的晚到,但是必须等待所有同学都到齐才能开始会议,这里的同学指的就是各个线程,会议就是CyclicBarrier.
2、如何使用CyclicBarrier
2.1 构造方法
publicCyclicBarrier(intparties) publicCyclicBarrier(intparties, RunnablebarrierAction)
解析:
- parties 是参与线程的个数
- 第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务
2.2 重要方法
public int await() throws InterruptedException, BrokenBarrierException public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
解析:
- 线程调用 await() 表示自己已经到达栅栏,每调用一次await()方法都将使阻塞的线程数+1,只有阻塞的线程数达到设定值时屏障才会打开,允许阻塞的所有线程继续执行。
- BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时。
- 带参数的方法表示只有在指定数量的线程到达时,或者等待时间超过timeout才会放行
3、案例实现
3.1 代码实现
publicclassCyclicBarrierDemo { staticclassTaskThreadextendsThread { CyclicBarrierbarrier; publicTaskThread(CyclicBarrierbarrier) { this.barrier=barrier; } publicvoidrun() { try { Thread.sleep(1000); System.out.println(getName() +" 进入会议 XXX"); //调用await()的时候,当前线程将会被阻塞,需要等待其他同学都到达await了才能继续barrier.await(); System.out.println(getName() +" 离开会议 XXX"); } catch (Exceptione) { e.printStackTrace(); } } } publicstaticvoidmain(String[] args) { intthreadNum=5; CyclicBarrierbarrier=newCyclicBarrier(threadNum, () ->System.out.println(Thread.currentThread().getName() +" 最后进入会议室")); for(inti=0; i<threadNum; i++) { newTaskThread(barrier).start(); } } }
3.2 打印结果
Thread-4进入会议XXXThread-2进入会议XXXThread-0进入会议XXXThread-1进入会议XXXThread-3进入会议XXXThread-3最后进入会议室Thread-3离开会议XXXThread-4离开会议XXXThread-1离开会议XXXThread-2离开会议XXXThread-0离开会议XXXProcessfinishedwithexitcode0
从打印结果可以看出,所有线程会等待全部线程到达栅栏之后才会继续执行,并且最后到达的线程会完成 Runnable 的任务。
4. 使用场景
可以用于多线程计算数据,最后合并计算结果的场景