在JDK API中是这么介绍的
一个同步辅助类它允许一组线程互相等待直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中这些线程必须不时地互相等待此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用所以称它为循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable 命令在一组线程中的最后一个线程到达之后(但在释放所有线程之前)该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态此屏障操作 很有用。
对于失败的同步尝试CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式如果因为中断、失败或者超时等原因导致线程过早地离开了屏障点那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException(如果它们几乎同时被中断则用 InterruptedException)以反常的方式离开。
CyclicBarrier分析CyclicBarrier结构如下
从上图可以看到CyclicBarrier内部使用ReentrantLock独占锁实现的。其构造函数如下
CyclicBarrier(int parties)创建一个新的 CyclicBarrier它将在给定数量的参与者(线程)处于等待状态时启动但它不会在启动 barrier 时执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction)创建一个新的 CyclicBarrier它将在给定数量的参与者(线程)处于等待状态时启动并在启动 barrier 时执行给定的屏障操作该操作由最后一个进入 barrier 的线程执行。
从上图可以看到CyclicBarrier内部使用ReentrantLock独占锁实现的。其构造函数如下
CyclicBarrier(int parties)创建一个新的 CyclicBarrier它将在给定数量的参与者(线程)处于等待状态时启动但它不会在启动 barrier 时执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction)创建一个新的 CyclicBarrier它将在给定数量的参与者(线程)处于等待状态时启动并在启动 barrier 时执行给定的屏障操作该操作由最后一个进入 barrier 的线程执行。
在CyclicBarrier中最重要的方法就是await()在所有参与者都已经在此 barrier 上调用 await 方法之前将一直等待。其源代码如下
await内部调用dowait():
1、首先判断该barrier是否已经断开了如果断开则抛出BrokenBarrierException异常
2、判断计算器index是否等于0如果等于0则表示所有的线程准备就绪已经到达某个公共屏障点了barrier可以进行后续工作了(是否执行某项任务(构造函数决定))然后调用nextGeneration方法进行更新换代工作(其中会唤醒所有等待的线程)
3、通过for循环(for(;;))使线程一直处于等待状态。直到“有parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生。
在dowait中有Generation这样一个对象。该对象是CyclicBarrier的一个成员变量
Generation描述着CyclicBarrier的更显换代。在CyclicBarrier中同一批线程属于同一代。当有parties个线程到达barriergeneration就会被更新换代。其中broken标识该当前CyclicBarrier是否已经处于中断状态。
对于中断CyclicBarrier是通过breakBarrier()实现的
在breakBarrier()中除了将broken设置为true还会调用signalAll将在CyclicBarrier处于等待状态的线程全部唤醒。
在超时的判断中CyclicBarrier根据timed的值来执行不同的wait。await、awaitNanos都是Condition中的方法。
当index –count等于0时标识“有parties个线程到达barrier”临界条件到达则执行相应的动作。执行完动作后则调用nextGeneration进行更新换代
示例1、线程等待到一定条件后才会继续进行。
——执行结果
2、线程等待到一定条件后执行某项任务。比如说我们等车只有当车坐满后汽车才会发动。
这个只需要对上面的代码进行小动作的改动即可
——-执行结果
喜欢的小伙伴点个关注哦