激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java多線程之同步工具類CountDownLatch

Java多線程之同步工具類CountDownLatch

2022-03-04 00:34冬日毛毛雨 Java教程

這篇文章主要介紹了Java多線程之同步工具類CountDownLatch,CountDownLatch是一個同步工具類,它允許一個或多個線程一直等待,直到其他線程執行完后再執行。例如,應用程序的主線程希望在負責啟動框架服務的線程已經啟動所有框架服

前言:

CountDownLatch是一個同步工具類,它允許一個或多個線程一直等待,直到其他線程執行完后再執行。例如,應用程序的主線程希望在負責啟動框架服務的線程已經啟動所有框架服務之后執行。

1 CountDownLatch主要方法

void await():如果當前count大于0,當前線程將會wait,直到count等于0或者中斷。 PS:當count等于0的時候,再去調用await()
線程將不會阻塞,而是立即運行。后面可以通過源碼分析得到。
boolean await(long timeout, TimeUnit unit):使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷或超出了指定的等待時間。
void countDown(): 遞減鎖存器的計數,如果計數到達零,則釋放所有等待的線程。
long getCount() :獲得計數的數量

2 CountDownLatch使用例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class CountDownLatchTest {
    private static final  int N = 4;
    public static void main(String[] args) {
 
        final CountDownLatch latch = new CountDownLatch(4);
 
        for(int i=0;i<N;i++)
        {
            new Thread(){
                public void run() {
                    try {
                        System.out.println("子線程"+Thread.currentThread().getName()+"正在執行");
                        Thread.sleep(3000);
                        System.out.println("子線程"+Thread.currentThread().getName()+"執行完畢");
                        latch.countDown();
                        System.out.println("剩余計數"+latch.getCount());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                };
            }.start();
        }
 
 
        try {
            System.out.println("等待"+N+"個子線程執行完畢...");
            latch.await();
            System.out.println(N+"個子線程已經執行完畢");
            System.out.println("繼續執行主線程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

子線程Thread-1正在執行
子線程Thread-3正在執行
子線程Thread-2正在執行
等待4個子線程執行完畢...
子線程Thread-0正在執行
子線程Thread-3執行完畢
子線程Thread-2執行完畢
剩余計數2
子線程Thread-1執行完畢
剩余計數1
子線程Thread-0執行完畢
剩余計數3
剩余計數0
4個子線程已經執行完畢
繼續執行主線程

3 CountDownLatch源碼分析

CountDownLatch是通過計數器的方式來實現,計數器的初始值為線程的數量。每當一個線程完成了自己的任務之后,就會對計數器減1,當計數器的值為0時,表示所有線程完成了任務,此時等待在閉鎖上的線程才繼續執行,從而達到等待其他線程完成任務之后才繼續執行的目的。

Java多線程之同步工具類CountDownLatch

構造函數

?
1
2
3
4
public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}

通過傳入一個數值來創建一個CountDownLatch,數值表示線程可以從等待狀態恢復,countDown方法必須被調用的次數

countDown方法

?
1
2
3
public void countDown() {
        sync.releaseShared(1);
    }

線程調用此方法對count進行減1。當count本來就為0,此方法不做任何操作,當count比0大,調用此方法進行減1,當new count為0,釋放所有等待當線程。

countDown方法的內部實現

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
  * Decrements the count of the latch, releasing all waiting threads if
  * the count reaches zero.
  *
  * <p>If the current count is greater than zero then it is decremented.
  * If the new count is zero then all waiting threads are re-enabled for
  * thread scheduling purposes.
  *
  * <p>If the current count equals zero then nothing happens.
  */
 public void countDown() {
     sync.releaseShared(1);
 }
 
 
 public final boolean releaseShared(int arg) {
     if (tryReleaseShared(arg)) {
         doReleaseShared();//釋放所有正在等待的線程節點
         return true;
     }
     return false;
 }
 
     protected boolean tryReleaseShared(int releases) {
         // Decrement count; signal when transition to zero
         for (;;) {
             int c = getState();
             if (c == 0)
                 return false;
             int nextc = c-1;
             if (compareAndSetState(c, nextc))
                 return nextc == 0;
         }
     }
 private void doReleaseShared() {
     for (;;) {
         Node h = head;
         if (h != null && h != tail) {
             int ws = h.waitStatus;
             if (ws == Node.SIGNAL) {
                 if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                     continue;            // loop to recheck cases
                 unparkSuccessor(h);
             }
             else if (ws == 0 &&
                      !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                 continue;                // loop on failed CAS
         }
         if (h == head)                   // loop if head changed
             break;
     }
 }

await方法

(1)不帶參數

?
1
2
3
public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}

調用此方法時,當count為0,直接返回true,當count比0大,線程會一直等待,直到count的值變為0,或者線程被中斷(interepted,此時會拋出中斷異常)。

(2)帶參數

?
1
2
3
4
public boolean await(long timeout, TimeUnit unit)
    throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

調用此方法時,當count為0,直接返回true,當count比0大,線程會等待一段時間,等待時間內如果count的值變為0,返回true;當超出等待時間,返回false;或者等待時間內線程被中斷,此時會拋出中斷異常。

await()方法的內部實現

?
1
2
3
public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

具體如下:

  • 1、檢測中斷標志位
  • 2、調用tryAcquireShared方法來檢查AQS標志位state是否等于0,如果state等于0,則說明不需要等待,立即返回,否則進行3
  • 3、調用doAcquireSharedInterruptibly方法進入AQS同步隊列進行等待,并不斷的自旋檢測是否需要喚醒
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
 
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}
/*
    函數功能:根據AQS的狀態位state來返回值,
    如果為state=0,返回 1
    如果state=1,則返回-1
*/
protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}
 
/**
 * Acquires in shared interruptible mode.
 * @param arg the acquire argument
 */
private void doAcquireSharedInterruptibly(int arg)
    throws InterruptedException {
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head) {
                int r = tryAcquireShared(arg);
                if (r >= 0) {//如果大于零,則說明需要喚醒
                    setHeadAndPropagate(node, r);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

4 CountDownLatch和CyclicBarrier區別

CountDownLatchCyclicBarrier都能夠實現線程之間的等待,只不過它們側重點不同:

  • CountDownLatch一般用于某個線程A等待若干個其他線程執行完任務之后,它才執行;
  • CyclicBarrier一般用于一組線程互相等待至某個狀態,然后這一組線程再同時執行;

CountDownLatch是不能夠重用的,而CyclicBarrier是可以重用的。

到此這篇關于Java多線程之同步工具類CountDownLatch的文章就介紹到這了,更多相關Java多線程 CountDownLatch內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/7020650400759939103

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久色免费| av电影手机在线看 | 国产午夜精品视频免费不卡69堂 | av久草| 青青草成人自拍 | 国产88久久久国产精品免费二区 | 亚洲一区二区观看播放 | 毛片视频播放 | 久久国产精品久久久久久 | 夫妻性生活交换 | chinese-xvideos| 国产91小视频在线观看 | 日韩av成人| 国产精品自拍av | 久久久久免费精品 | 精品一区二区久久久久 | 性日本xxx | 欧美精品18 | 国产成人综合在线 | 欧日韩在线视频 | 国产成人精品午夜视频' | 91短视频网页版 | 精品午夜久久 | 国产美女爽到喷白浆的 | 国产精品视频一区二区三区四 | 一区二区三区欧洲 | 日韩精品中文字幕在线观看 | 日本中文字幕网址 | 97精品视频在线观看 | 关键词 | 欧美成人精品一区二区三区 | 亚洲人成在线播放网站 | 日本一区二区高清不卡 | lutube成人福利在线观看污 | 亚洲精品久久久久久 | 在线视频成人永久免费 | 黄色av电影在线 | 国产精品午夜未成人免费观看 | 91精品国产一区二区三区四区在线 | 91精品国产九九九久久久亚洲 | 亚洲国产精品二区 |