1、概念
CyclicBarrier可循环使用的屏障,让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时屏障才会开门 ,所有被屏障拦截的线程才会继续运行。
CyclicBarrier和CountDownLatch一样,都是关于线程的计数器。
2.常用的方法:
CyclicBarrier(int parties)
创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。
解析:
- parties 是参与线程的个数
- 第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务
int await()
在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
int await(long timeout, TimeUnit unit)
在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
解析:
- 线程调用 await() 表示自己已经到达栅栏
- BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时
int getNumberWaiting()
返回当前在屏障处等待的参与者数目。
int getParties()
返回要求启动此 barrier 的参与者数目。
boolean isBroken()
查询此屏障是否处于损坏状态。
void reset()
将屏障重置为其初始状态。如果调用了该函数,则在等待的线程将会抛出BrokenBarrierException异常。
3 CyclicBarrier 使用场景
可以用于多线程计算数据,最后合并计算结果的场景
4代码实现
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class MyCyclicBarrier {
public static class ThreadRunable implements Runnable{
@Override
public void run() {
System.out.println(33);
}
}
public static void main(String[] args) throws InterruptedException
{
//2 是参与线程的个数
//new ThreadRunable() 最后一个到达线程要做的任务
CyclicBarrier barrier=new CyclicBarrier(2,new ThreadRunable());
new Thread(new Runnable(){
@Override
public void run() {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(11);
}
}).start();
try {
barrier.await();
System.out.println(22);
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
结果:33
11
22
CyclicBarrier 设置拦截线程数据量是2 ,所以必须等代码中的第一个线程 和ThreadRunable 都 执行完成后,
才会 继续执行主线程。