一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
public class Test{
public static void main(String[] arg){
//新建一个障栅,其会阻拦10个线程
CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
ThreadGroup group = new ThreadGroup("semaphore");//自定义线程组
AtomicInteger num = new AtomicInteger(0);
ThreadPoolExecutor pool = new ThreadPoolExecutor(
10,
10,
1000,
TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(20), new ThreadFactory() {//线程池工厂
@Override
public Thread newThread(Runnable r) {//生产新的线程
Thread thread = new Thread(group, r, group.getName()+"-thread-"+num.getAndIncrement());
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName()+"发生异常:"+e.getMessage());
}
});
return thread;
}
},new RejectedExecutionHandler() {//线程池的拒绝策略
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RuntimeException("任务队列已满,任务被拒绝");
}
});
//定义任务
Runnable task = ()->{
System.out.println("遇到了障栅....."+Thread.currentThread().getName()+"即将被阻塞");
try {
cyclicBarrier.await();
System.out.println("障栅放开了....."+Thread.currentThread().getName()+"即将休眠");
Thread.sleep(3000);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
};
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i = 0; i < 10; i++){//循环运行10个任务
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.execute(task);
}
if(Thread.activeCount() > 1){
Thread.yield();
}
pool.shutdown();
}
}
此外 CyclicBarrier提供了两个构造函数:
1:CyclicBarrier(int parties):创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动
2:CyclicBarrier(int parties, Runnable barrierAction) :创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行(即最后一个到达障栅点的线程执行参数中的barrierAction)
实例程序如下:
public class Test {
//使用工厂方法来创建 阻塞队列 ,实现解耦操作
private static class QueueFactory{
public static BlockingQueue getInstance(){
return new LinkedBlockingQueue<>();
}
}
public static void main(String[] args) {
//定义一个含有Runnable参数的,大小为3 的障栅
CyclicBarrier b = new CyclicBarrier(3,new Runnable() {
@Override
public void run() {
//最后一个到达障栅点的线程将执行此方法
System.out.println(Thread.currentThread().getName()+"----I am coming...");
}
});
//新建一个线程池 来跑线程
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3,
5,
1000,
TimeUnit.SECONDS,
QueueFactory.getInstance());
Runnable aRunnable = new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"----I am waiting...");
b.await();
} catch (InterruptedException|BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"----I am running...");
}
};
poolExecutor.execute(aRunnable);
poolExecutor.execute(aRunnable);
poolExecutor.execute(aRunnable);
poolExecutor.shutdown();
}
}
输出结果:
pool-1-thread-1----I am waiting...
pool-1-thread-3----I am waiting...
pool-1-thread-2----I am waiting...
pool-1-thread-2----I am coming... //最后一个到达障栅点的线程说了一句 I am coming...
pool-1-thread-2----I am running...
pool-1-thread-3----I am running...
pool-1-thread-1----I am running...
其实障栅的原理是Condition下面,我用Condition实现障栅的效果
public class Test {
//使用工厂方法来创建 阻塞队列 ,实现解耦操作
private static class QueueFactory{
public static BlockingQueue getInstance(){
return new LinkedBlockingQueue<>();
}
}
public static void main(String[] args) {
//下面三行代码模拟一个大小为3 的障栅
ReentrantLock aLock = new ReentrantLock();
//atomicInteger用于障栅计数
AtomicInteger atomicInteger = new AtomicInteger(3);
//通过condition.await()模拟障栅的await() 通过condition.signalAll()模拟障栅的释放
Condition acCondition = aLock.newCondition();
//新建一个线程池 来跑线程
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3,
5,
1000,
TimeUnit.SECONDS,
QueueFactory.getInstance());
Runnable aRunnable = new Runnable() {
@Override
public void run() {
aLock.lock();
try {
//如果atomicInteger==0 即所有的线程都来到了障栅点,所有线程可以继续执行了
if(atomicInteger.decrementAndGet() == 0){
System.out.println(Thread.currentThread().getName()+"----I am coming...");
//通过condition.signalAll()模拟障栅的释放
acCondition.signalAll();
}else{
System.out.println(Thread.currentThread().getName()+"----I am waiting...");
//通过condition.await()模拟障栅的await()
acCondition.await();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
aLock.unlock();
}
System.out.println(Thread.currentThread().getName()+"----I am running...");
}
};
poolExecutor.execute(aRunnable);
poolExecutor.execute(aRunnable);
poolExecutor.execute(aRunnable);
poolExecutor.shutdown();
}
}
pool-1-thread-1----I am waiting...
pool-1-thread-2----I am waiting...
pool-1-thread-3----I am coming...
pool-1-thread-3----I am running...
pool-1-thread-2----I am running...
pool-1-thread-1----I am running...