同步工具类----循环栅栏: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 任务分别是在 两个子任务线程中执行的。

posted @ 2019-04-26 12:13  波比爱吃肉  阅读(308)  评论(0编辑  收藏  举报