24.循环栅栏 CyclicBarrier


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

/**
 * CyclicBarrier可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 
 */
public class CyclicBarrierDemo extends Thread {
    private CyclicBarrier cyclicBarrier;
    public CyclicBarrierDemo(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println("子线程,"+Thread.currentThread().getName()+ " 开始写...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程,"+Thread.currentThread().getName()+ " 写完成...");
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("所有线程执行完毕...");
    }
    public static void main(String[] args){
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            CyclicBarrierDemo writer = new CyclicBarrierDemo(cyclicBarrier);
            writer.start();
        }
    }
    //子线程,Thread-0 开始写...
    //子线程,Thread-1 开始写...
    //子线程,Thread-2 开始写...
    //子线程,Thread-3 开始写...
    //子线程,Thread-4 开始写...
    //子线程,Thread-1 写完成...
    //子线程,Thread-0 写完成...
    //子线程,Thread-2 写完成...
    //子线程,Thread-4 写完成...
    //子线程,Thread-3 写完成...
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
}


/**
 * Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行
 */
public class CyclicBarrierDemo extends Thread {
    private CyclicBarrier cyclicBarrier;
    public CyclicBarrierDemo(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println("子线程,"+Thread.currentThread().getName()+ " 开始写...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程,"+Thread.currentThread().getName()+ " 写完成...");
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("所有线程执行完毕...");
    }
    public static void main(String[] args){
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("完成一个小目标");
            }
        });
        for (int i = 0; i < 5; i++) {
            CyclicBarrierDemo writer = new CyclicBarrierDemo(cyclicBarrier);
            writer.start();
        }
    }
    //子线程,Thread-0 开始写...
    //子线程,Thread-1 开始写...
    //子线程,Thread-2 开始写...
    //子线程,Thread-3 开始写...
    //子线程,Thread-4 开始写...
    //子线程,Thread-0 写完成...
    //子线程,Thread-2 写完成...
    //子线程,Thread-3 写完成...
    //子线程,Thread-4 写完成...
    //子线程,Thread-1 写完成...
    //完成一个小目标
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
    //所有线程执行完毕...
}

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

/**
 * CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
 * 循环栅栏 CyclicBarrier
 * 可以反复使用的计数器
 * 如:计数器设置为10,凑齐第一批10个线程后,计数器就会归零,然后接着凑齐下一批10个线程
 *
 *  public CyclicBarrier(int parties, Runnable barrierAction) //计数总数,线程总数
 */
public class CyclicBarrierDemo {
    public static class Soldier implements Runnable{
        private String soldier;
        private final CyclicBarrier cyclicBarrier;
        Soldier(String soldierName, CyclicBarrier cyclicBarrier) {
            this.soldier = soldierName;
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            try {
                //等待任务安排
                System.out.println("开始了");
                cyclicBarrier.await();
                doWork();
                //等待任务完成
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                //InterruptedException线程被中断
                //BrokenBarrierException:表示当前的cyclicBarrier已经破损了,避免其他线程进行永久的,无所谓的等待
                e.printStackTrace();
            }
        }

        void doWork() {
            try {
                Thread.sleep(Math.abs(new Random().nextInt()%10000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(soldier+":任务完成");
        }
    }
    public static class BarrierRun implements Runnable{
        boolean  flag;
        int N;

        public BarrierRun(boolean flag, int n) {
            this.flag = flag;
            N = n;
        }

        @Override
        public void run() {
            if (flag){
                System.out.println(N+"个任务已完成!");
            }else {
                System.out.println("安排"+N+"个任务!");
                flag = true;
            }
        }
    }
    public static void main(String[] args){
        final int N = 10;
        Thread[] allSoldier = new Thread[10];
        boolean flag = false;
        CyclicBarrier cyclic = new CyclicBarrier(N, new BarrierRun(flag, N));
        System.out.println("安排任务...");
        for (int i = 0; i < N; i++) {
            System.out.println("任务"+i+"安排");
            allSoldier[i] = new Thread(new Soldier("任务"+i,cyclic));
            allSoldier[i].start();
        }
    }
    //每运行完N个次数的任务就会执行BarrierRun任务

    //安排任务...
    //任务0安排
    //任务1安排
    //开始了
    //开始了
    //任务2安排
    //开始了
    //任务3安排
    //开始了
    //任务4安排
    //任务5安排
    //开始了
    //任务6安排
    //开始了
    //任务7安排
    //开始了
    //任务8安排
    //开始了
    //开始了
    //任务9安排
    //开始了
    //安排10个任务!
    //任务6:任务完成
    //任务3:任务完成
    //任务9:任务完成
    //任务5:任务完成
    //任务4:任务完成
    //任务0:任务完成
    //任务8:任务完成
    //任务7:任务完成
    //任务2:任务完成
    //任务1:任务完成
    //10个任务已完成!
}
原文地址:https://www.cnblogs.com/fly-book/p/11403481.html