CyclicBarrier迴環柵欄

CyclicBarrier,迴環柵欄,是併發包下的一個併發工具類。

場景舉例:奧運會百米賽場,等每一個運動員準備就位後,再開始準備比賽。java

運動員類
/**
 * 運動員類
 *
 * @author zhangjianbing
 * time 2020/8/16
 */
public class Athletes implements Runnable {

    private CyclicBarrier cyclicBarrier;

    private String name;

    public Athletes(CyclicBarrier cyclicBarrier, String name) {
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + "就位");
        try {
            cyclicBarrier.await();
            Random random = new Random();
            double time = random.nextDouble() + 9;
            System.out.println(name + ": " + time);
        } catch (Exception e) {

        }
    }

}
測試類
/**
 * @author zhangjianbing
 * time 2020/8/16
 */
public class Test01 {

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(8);

    public static void main(String[] args) {
        List<Athletes> athleteList = new ArrayList<>();
        athleteList.add(new Athletes(cyclicBarrier, "博爾特"));
        athleteList.add(new Athletes(cyclicBarrier, "鮑威爾"));
        athleteList.add(new Athletes(cyclicBarrier, "蓋伊"));
        athleteList.add(new Athletes(cyclicBarrier, "布雷克"));
        athleteList.add(new Athletes(cyclicBarrier, "加特林"));
        athleteList.add(new Athletes(cyclicBarrier, "蘇炳添"));
        athleteList.add(new Athletes(cyclicBarrier, "路人甲"));
        athleteList.add(new Athletes(cyclicBarrier, "路人乙"));
        Executor executor = Executors.newFixedThreadPool(8);
        for (Athletes athlete : athleteList) {
            executor.execute(athlete);
        }
        ((ExecutorService) executor).shutdown();
    }

}
測試結果:
博爾特就位
布雷克就位
鮑威爾就位
蓋伊就位
蘇炳添就位
加特林就位
路人乙就位
路人甲就位
加特林成績: 9.776372123476314
蓋伊成績: 9.967978419291022
路人乙成績: 9.748737769710981
博爾特成績: 9.046833555812153
路人甲成績: 9.933822348966673
蘇炳添成績: 9.34526967787858
布雷克成績: 9.717048683854648
鮑威爾成績: 9.548901062288996
CyclicBarrier構造參數中除了傳線程數量,還能夠傳一個Runnable,做用是在全部等待線程被喚醒後首先執行此線程,而後再進行後續操做。

改造上面的示例併發

運動員類,基本不變,增長了一次阻塞,目的是爲了等待全部運動員就緒,還增長了個容器,目的是存放比賽結果。
/**
 * 運動員類
 *
 * @author zhangjianbing
 * time 2020/8/16
 */
public class Athletes implements Runnable {

    private CyclicBarrier cyclicBarrier;

    private String name;

    private ConcurrentHashMap<String, Double> result;

    Athletes(ConcurrentHashMap<String, Double> result, CyclicBarrier cyclicBarrier, String name) {
        this.result = result;
        this.cyclicBarrier = cyclicBarrier;
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + "就位");
        try {
            cyclicBarrier.await();// 首次阻塞,目的等待全員就緒
            Random random = new Random();
            double time = random.nextDouble() + 9;
            System.out.println(name + "成績: " + time);
            result.put(name, time);// 比賽結果彙總
            cyclicBarrier.await();// 再次阻塞,目的統計比賽結果
        } catch (Exception e) {
            e.getStackTrace();
        }
    }

}
barrierAction類,此類的做用就是統計運動員成績。
/**
 * @author zhangjianbing
 * time 2020/8/16
 */
@Getter
@Setter
public class CompetitionResult implements Runnable {

    private ConcurrentHashMap<String, Double> result;

    CompetitionResult(ConcurrentHashMap<String, Double> result) {
        this.result = result;
    }

    @Override
    public void run() {
        if (!result.isEmpty()) {
            System.out.println("==========比賽結束成績彙總==========");
            System.out.println(sortMapByValue(result));
        } else {
            System.out.println("==========比賽開始==========");
        }
    }

    /** 從小到大排序 **/
    private List<String> sortMapByValue(Map<String, Double> map) {
        int size = map.size();
        List<Map.Entry<String, Double>> list = new ArrayList<>(size);
        list.addAll(map.entrySet());
        List<String> keys = list.stream()
                .sorted(Comparator.comparing(Map.Entry<String, Double>::getValue))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        List<String> rankList = new ArrayList<>();
        for (int i = 0; i < keys.size(); i++) {
            rankList.add("第" + (i + 1) + "名:" + keys.get(i));
        }
        return rankList;
    }

}
測試類,增長了CyclicBarrier構造參數以及一個全局的map容器用來存放比賽結果。
/**
 * @author zhangjianbing
 * time 2020/8/16
 */
public class Test01 {

    /** 將統計的結果都放到map中保存,以便統計成績 **/
    private static ConcurrentHashMap<String, Double> result = new ConcurrentHashMap<>();

    /** barrierAction線程統計 **/
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(8, new CompetitionResult(result));

    public static void main(String[] args) {
        List<Athletes> athleteList = new ArrayList<>();
        athleteList.add(new Athletes(result, cyclicBarrier, "博爾特"));
        athleteList.add(new Athletes(result, cyclicBarrier, "鮑威爾"));
        athleteList.add(new Athletes(result, cyclicBarrier, "蓋伊"));
        athleteList.add(new Athletes(result, cyclicBarrier, "布雷克"));
        athleteList.add(new Athletes(result, cyclicBarrier, "加特林"));
        athleteList.add(new Athletes(result, cyclicBarrier, "蘇炳添"));
        athleteList.add(new Athletes(result, cyclicBarrier, "路人甲"));
        athleteList.add(new Athletes(result, cyclicBarrier, "路人乙"));

        Executor executor = Executors.newFixedThreadPool(8);
        for (Athletes athlete : athleteList) {
            executor.execute(athlete);
        }
        ((ExecutorService) executor).shutdown();
    }

}
運行結果:
博爾特就位
布雷克就位
蓋伊就位
蘇炳添就位
鮑威爾就位
加特林就位
路人甲就位
路人乙就位
==========比賽開始==========
路人甲成績: 9.987082768602964
蓋伊成績: 9.437668731148879
加特林成績: 9.173731719193814
路人乙成績: 9.169443283692779
博爾特成績: 9.11962473264503
鮑威爾成績: 9.138726087475982
蘇炳添成績: 9.607073596518454
布雷克成績: 9.294505506699329
==========比賽結束成績彙總==========
[第1名:博爾特, 第2名:鮑威爾, 第3名:路人乙, 第4名:加特林, 第5名:布雷克, 第6名:蓋伊, 第7名:蘇炳添, 第8名:路人甲]
CyclicBarrier總結:
  1. 構造參數中,線程數量必須和await的線程數量相等,不然永遠阻塞。
  2. 構造參數中的Runnable做用是在全部線程都到達屏障後優先執行此線程,,能夠作一些統計工做,這多是柵欄的含義。
  3. await方法能夠屢次調用,實現屢次運行,這多是迴環含義。
相關文章
相關標籤/搜索