成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:CyclicBarrier有了解過嗎?

開發 開發工具
Java提供了一些非常好用的并發工具類,不需要我們重復造輪子,本節我們講解CyclicBarrier,一起來看下吧~

前言

Java提供了一些非常好用的并發工具類,不需要我們重復造輪子,本節我們講解CyclicBarrier,一起來看下吧~

CyclicBarrier

這個跟我們上節講的CountDownLatch有點類似,從字面意思講是相當于一個可循環的屏障,他與CountDownLatch不同的是它可以重復利用,下一步的操作以,依賴上一步是否完成,就像去銀行辦業務一樣,排在你前面的人辦好了才輪到你,我們繼續通過上節的例子,來改寫一下它,這里我偷個懶,實際業務中盡量用類編寫,不要直接new Thread。

public class CyclicBarrierTest {    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {        CyclicBarrier cyclicBarrier = new CyclicBarrier(1);        IntStream.range(0, 10).forEach(i -> {            new Thread(() -> {                try {                    Thread.sleep(2000);                    System.out.println("worker 1------> " + i);                    cyclicBarrier.await();                    Thread.sleep(2000);                    System.out.println("worker 2------> " + i);                    cyclicBarrier.await();                    Thread.sleep(2000);                    System.out.println("worker 3------> " + i);                    cyclicBarrier.await();                } catch (InterruptedException | BrokenBarrierException e) {                    e.printStackTrace();                }            }).start();        });        System.out.println("completed !");    }}

實際輸出:

completed !worker 1------> 9worker 1------> 0worker 1------> 6worker 1------> 7worker 1------> 5worker 1------> 4worker 1------> 1worker 1------> 3worker 1------> 2worker 1------> 8worker 2------> 7worker 2------> 6worker 2------> 5worker 2------> 2worker 2------> 3worker 2------> 1worker 2------> 8worker 2------> 0worker 2------> 9worker 2------> 4worker 3------> 6worker 3------> 3worker 3------> 2worker 3------> 5worker 3------> 7worker 3------> 8worker 3------> 1worker 3------> 0worker 3------> 9worker 3------> 4

可以看到在即使在多線程下,每個操作都需要上一個await任務之后執行,使用很簡單,也很好理解。

知其然知其所以然 & 源碼剖析

下面我們就一起探究一下,它是如何做到的?

同樣的,我們先看構造函數。

public CyclicBarrier(int parties) {    this(parties, null);}public CyclicBarrier(int parties, Runnable barrierAction) {    if (parties <= 0) throw new IllegalArgumentException();    this.parties = parties;    this.count = parties;    this.barrierCommand = barrierAction;}

?默認barrierAction是null, 這個參數是Runnable參數,當最后線程達到的時候執行的任務,剛剛的例子中沒有演示,大家可以在初始化的時候傳入一個,打印一下當前的線程名稱,這樣理解起來比較容易點,parties int型,它的意思是參與的線程數。

我們再看它的定義, 可以看到它沒有繼承任何類或實現任何接口?。

public class CyclicBarrier { .... }

await

我們重點看下這個方法。

public int await() throws InterruptedException, BrokenBarrierException {    try {        return dowait(false, 0L);    } catch (TimeoutException toe) {        throw new Error(toe); // cannot happen    }}

這個方法干嘛用的呢?等到所有各方都在此屏障上調用了await 。如果當前線程不是最后到達的,則出于線程調度目的將其禁用并處于休眠狀態,除了以下情況:

  • 最后一個線程到達;或者。
  • 其他一些線程中斷當前線程;或者。
  • 其他一些線程中斷了其他等待線程之一;或者。
  • 其他一些線程在等待屏障時超時;或者。
  • 其他一些線程在此屏障上調用reset 。

再看dowait(), 它是一個私有方法。

private int dowait(boolean timed, long nanos)        throws InterruptedException, BrokenBarrierException,               TimeoutException {        // 全局鎖                final ReentrantLock lock = this.lock;        lock.lock();        try {            // 每次使用屏障都會生成一個實例            // private Generation generation = new Generation();            final Generation g = generation;            // broken字面意思破壞,如果被破壞了就拋異常            if (g.broken)                throw new BrokenBarrierException();            // 線程中斷檢測            if (Thread.interrupted()) {                breakBarrier();                throw new InterruptedException();            }            // 剩余的等待線程數            int index = --count;            // 最后線程到達時             if (index == 0) {  // tripped                // 標記任務是否被執行(就是傳進入的runable參數)                boolean ranAction = false;                try {                    final Runnable command = barrierCommand;                    // 執行任務                    if (command != null)                        command.run();                    ranAction = true;                    // 完成后 進行下一組 初始化 generation 初始化 count 并喚醒所有等待的線程                     //                     // private void nextGeneration() {                    //     // signal completion of last generation                    //     trip.signalAll();                    //     // set up next generation                    //     count = parties;                    //     generation = new Generation();                    // }                    nextGeneration();                    return 0;                } finally {                    if (!ranAction)                        breakBarrier();                }            }            // index 不為0時 進入自旋            for (;;) {                try {                    // 先判斷超時 沒超時就繼續等著                    if (!timed)                        trip.await();                        // 如果超出指定時間 調用 awaitNanos 超時了釋放鎖                    else if (nanos > 0L)                        nanos = trip.awaitNanos(nanos);                        // 中斷異常捕獲                } catch (InterruptedException ie) {                    // 判斷是否被破壞                    if (g == generation && ! g.broken) {                        //  private void breakBarrier() {                        //     generation.broken = true;                        //     count = parties;                        //     trip.signalAll();                        // }                        breakBarrier();                        throw ie;                    } else {                        // 否則的話中斷當前線程                        Thread.currentThread().interrupt();                    }                }                // 被破壞拋異常                if (g.broken)                    throw new BrokenBarrierException();                // 正常調用 就返回                 if (g != generation)                    return index;                // 超時了而被喚醒的情況 調用 breakBarrier()                if (timed && nanos <= 0L) {                    breakBarrier();                    throw new TimeoutException();                }            }        } finally {            // 釋放鎖            lock.unlock();        }    }

如果被破壞了怎么恢復呢?來看下reset, 源碼很簡單,break之后重新生成新的實例,對應的會重新初始化count,在dowait里index==0也調用了nextGeneration,所以說它是可以循環利用的。

public void reset() {    final ReentrantLock lock = this.lock;    lock.lock();    try {        breakBarrier();   // break the current generation        nextGeneration(); // start a new generation    } finally {        lock.unlock();    }}

結束語

cyclicBarrier源碼相對簡單一些,下節給大家講下Phaser,它是增強版的CountDownLatch,它的實現相對更加復雜一點 。

責任編輯:姜華 來源: 今日頭條
相關推薦

2022-07-26 08:40:42

Java并發工具類

2022-07-11 10:47:46

容器JAVA

2022-06-10 13:56:42

Java

2022-06-30 08:14:05

Java阻塞隊列

2022-06-09 11:20:44

volatile關鍵字

2022-06-15 15:14:17

Java公平鎖非公平鎖

2022-06-08 13:54:23

指令重排Java

2022-06-30 14:31:57

Java阻塞隊列

2022-06-24 06:43:57

線程池線程復用

2022-07-18 14:18:26

Babel代碼面試

2021-04-12 21:34:29

Redis故障數據

2024-09-09 08:30:56

代碼

2022-06-02 09:29:55

線程組線程樹狀結構

2020-09-26 22:04:32

數據安全傳輸HTTPSHTTP 協議

2024-09-03 07:58:46

2020-10-08 14:15:15

Zookeeper

2023-02-20 08:08:48

限流算法計數器算法令牌桶算法

2025-03-26 01:25:00

MySQL優化事務

2024-03-07 17:21:12

HotSpotJVMHot Code

2019-12-25 11:22:19

負載均衡集群算法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日日爱夜夜操 | 久久久久9999亚洲精品 | 97精品超碰一区二区三区 | 成人精品一区二区 | 久久久国产精品一区 | 91婷婷韩国欧美一区二区 | 欧美日韩综合 | 羞羞视频免费观看 | 免费观看av | 在线电影日韩 | 成人久久视频 | jizz视频 | 亚洲日产精品 | 国产精品高潮呻吟久久久久 | 日本在线视频不卡 | 亚洲欧美一区二区三区在线 | 亚洲人在线| 欧美精品一区二区三区四区 | 国产精品美女久久久久aⅴ国产馆 | 五月免费视频 | 色香蕉在线| 激情五月综合网 | 国产精品久久久久一区二区三区 | 精品国产黄a∨片高清在线 www.一级片 国产欧美日韩综合精品一区二区 | 亚洲xx在线 | 国产成人免费视频网站高清观看视频 | 女女爱爱视频 | 国产精品亚洲精品日韩已方 | 中文字幕免费视频 | 天天干b| 狠狠爱综合 | 超碰av免费 | 天堂成人国产精品一区 | 日本黄色片免费在线观看 | jizz在线免费观看 | 麻豆国产精品777777在线 | 日韩精品亚洲专区在线观看 | 超碰电影| 91亚洲精选 | 欧美一级三级 | 精品一二|