①CyclicBarrier(栅栏),也就是可循环利用的屏障,可循环利用就是说该类创建的对象可以进行复用;屏障就是指每次线程运行时,都会碰到一个屏障,直到所有线程执行完毕,然后屏障才会才开,所有线程继续往下执行;CyclicBarrier是CountDownLatch的增强版本,增加了重置功能(通过其内部静态类Generation来实现重置功能)。
②CyclicBarrier的构造函数
(1)CyclicBarrier(int parties):parties(需要拦截的线程数)。
(2)CyclicBarrier(int parties, Runnable barrierAction):parties(表示需要拦截的线程数)、barrierAction(表示等待的线程中到达屏障是优先执行的Runnable对象)。
③CyclicBarrier(栅栏)的原理:内部定义了一个ReentrantLock(可重入得互斥锁)对象进行线程的安全控制。
④CyclicBarrier的API介绍:
1)Generation内部静态类(实现重置功能):
(1)源码:
(2)重置的方法:为CyclicBarrier实例中的域来重新创建一个新的Generation即可。
private static class Generation {
//判断当前的屏障是否被打断了
boolean broken = false;
}
(3)类的中内置属性:
//所有方法的共享锁,可重入的互斥锁
private final ReentrantLock lock = new ReentrantLock();
//通过可重入的互斥锁得到的一个状态变量
private final Condition trip = lock.newCondition();
//总的等待线程的数量。
private final int part //屏障正常打开后优先运行的线程
private final Runnable barrierCommand;
//当前的Generation。每次屏障失效或者开闸之后,该独享都会自动被替换掉,从而实现重置的功能。
private Generation generation = new Generation();
(4)await()方法
1)功能:调用该方法的线程会等待直到有足够数量的线程调用该方法(也就是我们说得开闸状态)
2)打破该状态的方法:
1、当最后一个线程到达。
2、有其他线程中断当前线程(抛出InterruptException异常)。
3、指定了限时操作,并到达时限时间(抛出TimeoutException异常)。
4、barrier被重置或屏障的地方处理打破状态(抛出BrokenBarrierException)。
3)两个需要锁的子方法
//在屏障开闸之后重置状态,以待下一次调用
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
//实际上是在屏障打破之后设定打破状态(已唤醒其它线程并通知)
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
(5)reset()方法(重建屏障方法):
1)源码
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); //打破当前的屏障
nextGeneration();//重新配置重置对象Generation
} finally {
lock.unlock();
}
}
2)注意点:只有先打破当前屏障,才能再重建一个新的屏障,否则可能导致信号丢失。
package com.atlihao.test;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;这里写代码片
import org.junit.jupiter.api.Test;
//高并发之栅栏
public class CyclicBarrierTest {
@Test
public void test1() {
//并发线程数
int count = 10000;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
ExecutorService executorService = Executors.newFixedThreadPool(count-1);
int n = 0;
for (int i = 0; i < count; i++) {
executorService.execute(new CyclicBarrierTest().new Task(cyclicBarrier, n));
n++;
}
executorService.shutdown(); // 关闭线程池
// 判断是否所有的线程已经运行完
while (!executorService.isTerminated()) {
try {
// 所有线程池中的线程执行完毕,执行后续操作
System.out.println("==============is sleep============");
Thread.sleep(10000);
System.out.println("==============is wake============");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Task implements Runnable {
private CyclicBarrier cyclicBarrier;
int n = 0;
public Task(CyclicBarrier cyclicBarrier, int n) {
this.cyclicBarrier = cyclicBarrier;
this.n = n;
}
@Override
public void run() {
try {
// 等待所有任务准备就绪
System.out.println("选手" + n + "到达起跑线前");
cyclicBarrier.await();
System.out.println("选手" + n + "开始跑");
// 测试内容
System.out.println("hello: " + n);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
对CyclicBarrier(栅栏)的简单使用吧。