同步工具类-----循环栅栏:CyclicBarrier

Posted jvjs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同步工具类-----循环栅栏:CyclicBarrier相关的知识,希望对你有一定的参考价值。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class TestCyclicBarrier {
public static class Soldier implements Runnable { private String soldier; private final CyclicBarrier cyclicBarrier; private long timeout; public Soldier(CyclicBarrier cyclicBarrier, String soldier, long timeout) { this.cyclicBarrier = cyclicBarrier; this.timeout = timeout; this.soldier = soldier; } @Override public void run() { try { // 等待所有士兵到齐 cyclicBarrier.await(); doWork(); // 等待所有士兵完成工作 cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } void doWork() { try { // Thread.sleep(Math.abs(new Random().nextInt() % 100000)); Thread.sleep(timeout); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(soldier + ":任务完成!【用时: " + timeout / 1000 + " 秒】, " + "当前线程:" + Thread.currentThread().getName()); } } public static class BarrierRun implements Runnable { boolean flag; int N; private BarrierRun(boolean flag, int n) { this.flag = flag; N = n; } @Override public void run() { if (flag) { System.err.println("司令:【士兵" + N + "个,任务完成!】," + "【当前执行线程:" + Thread.currentThread().getName() + "】"); } else { System.err.println("司令:【士兵" + N + "个,集合完毕!】," + "【当前执行线程:" + Thread.currentThread().getName() + "】"); flag = true; } } } public static void main(String[] args) throws InterruptedException { final int N = 10; Thread[] soldierThreads = new Thread[N]; boolean flag = false;
     // CyclicBarrier 可以接收一个Runnable类型参数作为barrierAction
// 所谓barrierAction就是当计数器一次计数完成(成功通过栅栏)后的栅栏操作,系统会在一个子任务线程中)执行的动作,但在阻塞线程被释放前是不能执行的
// 如果所有线程都成功地通过了栅栏,那么await将为每个线程返回一个唯一的到达索引号,我们可以利用这些索引来“选举”产生一个领导线程,并在下一次迭代中由该领导线程执行一些特殊的工作。
CyclicBarrier cyclicBarrier
= new CyclicBarrier(N, new BarrierRun(flag, N)); System.err.println("集合队伍!"); TimeUnit.SECONDS.sleep(1); String tname; for (int i = 0; i < N; ++i) { System.out.println("士兵" + i + "报道!"); long timeout = (int) (1 + Math.random() * 10) * 1000; tname = "士兵" + i; soldierThreads[i] = new Thread(new Soldier(cyclicBarrier, tname, timeout), tname); // soldierThreads[i].setName(tname); soldierThreads[i].start(); /*if( i == 5){ soldierThreads[i].interrupt(); }*/ } } }

执行结果:

  1. 可见两次BarrierRun 任务分别是在 两个子任务线程中执行的。

技术图片

以上是关于同步工具类-----循环栅栏:CyclicBarrier的主要内容,如果未能解决你的问题,请参考以下文章

同步工具类(锁闭锁栅栏信号量)

J.U.C 的同步工具类

Java编程的逻辑 (81) - 并发同步协作工具

源码分析:CyclicBarrier 之循环栅栏

JUC并发编程 共享模式之工具 JUC CyclicBarrier(循环栅栏 与CountdownLatch最大的不同是可以重值倒计时) -- CyclicBarrier介绍使用注意事项

Java并发编程学习8-同步工具类