同步工具类可以是任何一个对象,只要它根据其自身的状态来协调线程的控制流。阻塞队列可以作为同步工具类,其他类型的同步工具类还包括 信号量(Semaphore)、栅栏(CyclicBarrier)以及闭锁(Latch)。
本文重点介绍CyclicBarrier的使用以及应用场景。
CyclicBarrier
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier方法列表
构造函数:
- CyclicBarrier(int parties):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。
- CyclicBarrier(int parties, Runnable barrierAction):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。
方法:
- int await():在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
- int await(long timeout, TimeUnit unit):在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
- int getNumberWaiting():返回当前在屏障处等待的参与者数目。
- int getParties():返回要求启动此 barrier 的参与者数目。
- boolean isBroken():查询此屏障是否处于损坏状态。
- void reset():将屏障重置为其初始状态。
示例
package com.bytebeats.concurrent.api;
import java.util.Random;
import java.util.concurrent.*;
/**
* ${DESCRIPTION}
*
* @author Ricky Fung
* @create 2017-04-24 23:13
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
int parties = 5;
ExecutorService pool = Executors.newFixedThreadPool(parties);
final CyclicBarrier barrier = new CyclicBarrier(parties);
for(int i=0; i<parties; i++){
Runnable task = new Runnable() {
@Override
public void run() {
try {
int time = new Random().nextInt(5000);
TimeUnit.MILLISECONDS.sleep(time);
System.out.println("thread "+Thread.currentThread().getName()+" 到达集合点");
barrier.await(); //到达集合点, 数量加1
System.out.println("thread "+Thread.currentThread().getName()+" 通过集合点继续往后执行");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
pool.execute(task);
}
pool.shutdown();
}
}
源码下载
https://github.com/TiFG/daily-codelab/tree/master/concurrent-api-sample