CyclicBarrier :
作用:一个同步辅助工具,它允许一组线程全部进行相互等待彼此到达公共的屏障点后,相互等待的线程会进行并发执行后续的代码逻辑
它同时实现了可循环的屏障操作,并且在屏障释放前可以执行额外的一个操作。
应用场景:
非常适合固定大小的线程的程序中使用,这些线程间或彼此等待。
实际项目场景的应用:
数据的采用多线程的组装
使用方式:
1. 创建好 CyclicBarrier 实例,并指定有多个线程会参与相互等待
2. 在屏障点处,用CyclicBarrier 实例调用其await() 方法进行等待,当最后一个线程到达屏障点后,全部等待的线程都会被唤醒,从而执行后续的代码逻辑
底层实现:
在 CyclicBarrier 中,它的成员变量有如下:
1. ReetrantLock类型的实例 lock: 该锁主要是保证屏障进入,
2. 与lock 相关联的 Condiction类型实例 trip :
3. int parties : 它是指参与屏障等待的线程总个数
4. Generation 类型实例 generation :
当count 为0时,表示当前阶段所有线程都到达了各自的屏障点,此时会进行新一轮周期的屏障操作,
在 nextGenneration() 方法中,会调用 trip.signalAll() 来唤醒所有等待线程,去执行它们后续代码逻辑。
同时它会将count 赋值为 parties, 并创建一个新的 Generation 实例。
当count > 0时,直接调用 trip.await() 方法,将当前线程挂起,并释放锁资源。
5. int count : 记录当前 Generation(本代) 彼此相互等待的线程未到达其屏障点的个数
6. Runnable 类型实例 barriweCommand :
在CyclicBarrier 中的阻塞线程是通过 Lock中对应的 Condiction 实例,去调用了await 方法,然后所有的线程到达屏障点时,
触发 condiction 调用 signalAll 方法,将所有线程唤醒,然后去执行后续代码。
以下为代码示例:
public class CyclicBarrierTest {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
CyclicBarrier countDownLatch = new CyclicBarrier(5,()->{
System.out.println("线程执行完成 ,开始合并数据");
try {
Thread.sleep((long) (Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("合并数据完成");
System.out.println("集合数据:" + arrayList);
});
IntStream.range(0,10).forEach(i -> new Thread(()->{
System.out.println(String.format("线程:%s开始执行任务",Thread.currentThread().getName()));
try {
Thread.sleep((long) (Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
arrayList.add(Thread.currentThread().getName());
System.out.println(String.format("线程:%s执行任务完成",Thread.currentThread().getName()));
countDownLatch.await();//进入屏障点
} catch (Exception e) {
e.printStackTrace();
}
}).start());
}
}