介绍
CyclicBarrier(可循环屏障)是一个线程同步辅助类,可用于多个线程之间相互等待,而且是可循环使用的。使用时需要在相互等待的线程中传入同一个CyclicBarrier对象,通过调用CyclicBarrier对象的await()
方法实现等待,在所有的线程都运行到await()
方法处时,所有的线程等待结束,一起向下执行。CyclicBarrier实例化时需要传入执行的线程数,这点与CountDownLatch(线程计数器)相同,可以看作是能重复使用的CountDownLatch。CyclicBarrier的构造方法中还可以传入一个Runnable对象,用于所有的线程都运行到等待位置时一起调用。
常用方法列表
//构造函数,传入线程数和等待完成后执行的动作
CyclicBarrier(int parties, Runnable barrierAction);
//构造函数,只传入线程数,等待完成无特定动作
CyclicBarrier(int parties);
//获取实例化时传入的线程数
int getParties();
//使当前线程在所有线程都运行到这里之前一直等待,除非线程被中断。
int await();
//使当前线程在所有线程都运行到这里之前一直等待,除非线程被中断或超出了指定的等待时间。
int await(long timeout, TimeUnit unit);
//查询此屏障是否处于断开状态
boolean isBroken();
//将屏障重置为初始状态
void reset();
//返回当前在屏障处等待的线程数,此方法主要用于调试和断言。
int getNumberWaiting();
应用示例
public class CyclicBarrierTest {
private static CyclicBarrier cyclicBarrier;
private static int NUM = 5;
public static void main(String[] args) {
//设置屏障的线程数量,和所有子线程都执行完一遍后要执行的代码
cyclicBarrier = new CyclicBarrier(NUM,()-> System.out.println("所有的子线程都运行到了屏障位置"));
for (int i = 0; i < NUM; i++) {
new Thread(new MyTask(),"子线程"+i).start();
}
System.out.println("主线程结束");
}
static class MyTask implements Runnable{
@Override
public void run() {
for(int i=0;i<2;i++){
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"开始执行");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(thread.getName()+"执行到屏障位置");
try {
//每个子线程执行到这里都会等待其他的子线程执行到这里
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(thread.getName()+"执行结束");
}
}
}
}
运行结果
子线程1开始执行
子线程2开始执行
子线程4开始执行
子线程3开始执行
主线程结束
子线程0开始执行
子线程2执行到屏障位置
子线程4执行到屏障位置
子线程3执行到屏障位置
子线程1执行到屏障位置
子线程0执行到屏障位置
所有的子线程都运行到了屏障位置
子线程0执行结束
子线程0开始执行
子线程2执行结束
子线程2开始执行
子线程4执行结束
子线程4开始执行
子线程1执行结束
子线程1开始执行
子线程3执行结束
子线程3开始执行
子线程1执行到屏障位置
子线程4执行到屏障位置
子线程2执行到屏障位置
子线程0执行到屏障位置
子线程3执行到屏障位置
所有的子线程都运行到了屏障位置
子线程3执行结束
子线程1执行结束
子线程4执行结束
子线程2执行结束
子线程0执行结束