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總結: