最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JUC系列學(xué)習(xí)工具類CountDownLatch詳解

 更新時間:2022年08月18日 09:05:49   作者:劍圣無痕  
這篇文章主要介紹了JUC系列學(xué)習(xí)工具類CountDownLatch詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可任意參考一下

前言:

項目中我們經(jīng)常會遇到有時候需要等待其他線程完成任務(wù)后,主線程才能執(zhí)行其他任務(wù),那么我們將如何實現(xiàn)呢?

Join 解決方案

join 的工作原理是,檢查thread是否存活,如果存活則讓當(dāng)前線程永遠(yuǎn)wait,直到 thread線程終止,線程的 notifyAll才會被調(diào)用。

具體實現(xiàn)

public class JoinAThread extends Thread
{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + 
                " 線程開始");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
         System.out.println( Thread.currentThread().getName() + 
                " 線程執(zhí)行完畢");
    }
}

public class JoinBThread extends Thread
{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + 
                " 線程開始");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
         System.out.println( Thread.currentThread().getName() + 
                " 線程執(zhí)行完畢");
    }
}

public class JoinTest
{
   public static void main(String[] args) throws InterruptedException
{
       JoinAThread joinA =new JoinAThread();
       Thread threadA =new Thread(joinA,"線程A");

       JoinBThread joinB =new JoinBThread();
       Thread threadB =new Thread(joinB,"線程B");
       threadA.start();
       threadB.start();
       threadA.join();
       threadB.join();

       System.out.println("子線程執(zhí)行完成了,主線程"+Thread.currentThread().getName()+"開始執(zhí)行了");
     }
}

執(zhí)行結(jié)果

從結(jié)果中,我們可以看出只有子線程執(zhí)行完成了,主線程才開始執(zhí)行。join的實現(xiàn)我們需要每個線程進行join,如果存在多個線程,那么寫起來會比較的繁瑣,那么又沒更新優(yōu)化的方案了,答案是JUC下面的工具類CountDownLatch,也能完成同樣的功能。

CountDownLatch 解決方案

具體實現(xiàn)

public class CountDownLatchTest
{
    private static Logger logger =LoggerFactory.getLogger(CountDownLatchTest.class);
    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService exec = Executors.newCachedThreadPool();
        final CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 1; i <= 10; i++){
            exec.execute(() -> {
                try {
                    invokeServiec();
                } catch (InterruptedException e) 
                {
                    logger.info("invoce service error",e);
                }
                finally 
                {
                    //計數(shù)器減一
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        logger.info("所有的子線程執(zhí)行完成,主線程"+Thread.currentThread().getName()+"開始執(zhí)行");
    }

    private static void invokeServiec() throws InterruptedException
    {
        logger.info(Thread.currentThread().getName()+",開始執(zhí)行任務(wù)");
        Thread.sleep(300);
    }
}

說明:CountDownLatch中有兩個方法一個是await()方法,調(diào)用這個方法的線程會被阻塞,另外一個是countDown() 方法,調(diào)用此方法會使計數(shù)器減一,當(dāng)計數(shù)器的值為0時,調(diào)用await()方法被阻塞的線程才會被喚醒。

執(zhí)行結(jié)果:

原理說明

CountDownLatch 是一個計數(shù)器閉鎖,通過它可以完成類似于阻塞當(dāng)前線程的功能,即:一個線程或多個線程一直等待,直到其他線程執(zhí)行的操作完成。

基本原理

CountDownLatch

CountDownLatch內(nèi)部定義計數(shù)器和一個隊列。當(dāng)計數(shù)器的值遞減為0之前,阻塞隊列里面的線程處于掛起狀態(tài),當(dāng)計數(shù)器遞減到0時會喚醒阻塞隊列所有線程,計數(shù)器是一個標(biāo)志,可以表示一個任務(wù)一個線程,也可以表示一個倒計時器。

常用的方法

countDown:用于使計數(shù)器減一,其一般是執(zhí)行任務(wù)的線程調(diào)用. await: 使用線程處于等待狀態(tài),其一般是主線程調(diào)用.

countDown

countDown實現(xiàn)方法如下:

說明:sync是一個AQS的隊列,調(diào)用的為AQS的releaseShared方法,其具體實現(xiàn)如下:

而releaseShared調(diào)用為CountDownLatch中的內(nèi)部類sync中的tryReleaseShared方法,具體實現(xiàn)如下:

tryReleaseShared(int)方法即對state屬性進行減一操作的代碼.通過CAS進行減操作來保證原子性,其會比較state是否為c,如果是則將其設(shè)置為nextc(自減1),如果state不為c,則說明有另外的線程在getState()方法和compareAndSetState()方法調(diào)用之間對state進行了設(shè)置,當(dāng)前線程也就沒有成功設(shè)置state屬性的值,其會進入下一次循環(huán)中,如此往復(fù),直至其成功設(shè)置state屬性的值,即countDown()方法調(diào)用成功。

而doReleaseShared方法調(diào)用的為AbstractQueuedSynchronizer簡稱AQS的doReleaseShared方法,

說明:首先判斷頭結(jié)點不為空,且不為尾節(jié)點,說明等待隊列中有等待喚醒的線程,這里需要說明的是,在等待隊列中,頭節(jié)點中并沒有保存正在等待的線程,其只是一個空的Node對象,真正等待的線程是從頭節(jié)點的下一個節(jié)點開始存放的,因而會有對頭結(jié)點是否等于尾節(jié)點的判斷。在判斷等待隊列中有正在等待的線程之后,其會清除頭結(jié)點的狀態(tài)信息,并且調(diào)用unparkSuccessor(Node)方法喚醒頭結(jié)點的下一個節(jié)點,使其繼續(xù)往下執(zhí)行。如下是unparkSuccessor(Node)方法的具體實現(xiàn):

可以看到,unparkSuccessor(Node)方法的作用是喚醒離傳入節(jié)點最近的一個處于等待狀態(tài)的線程,使其繼續(xù)往下執(zhí)行。

await

await方法實現(xiàn)如下:

await()方法調(diào)用了Sync對象的方法acquireSharedInterruptibly(int)方法,該方法的具體實現(xiàn)如下:

g

在doAcquireSharedInterruptibly(int)方法中,首先使用當(dāng)前線程創(chuàng)建一個共享模式的節(jié)點。然后在一個for循環(huán)中判斷當(dāng)前線程是否獲取到執(zhí)行權(quán)限,如果有(r >= 0判斷)則將當(dāng)前節(jié)點設(shè)置為頭節(jié)點,并且喚醒后續(xù)處于共享模式的節(jié)點;如果沒有,則對調(diào)用shouldParkAfterFailedAcquire(Node, Node)和parkAndCheckInterrupt()方法使當(dāng)前線程處于"擱置"狀態(tài),該"擱置"狀態(tài)是由操作系統(tǒng)進行的,這樣可以避免該線程無限循環(huán)而獲取不到執(zhí)行權(quán)限,造成資源浪費,這里也就是線程處于等待狀態(tài)的位置,也就是說當(dāng)線程被阻塞的時候就是阻塞在這個位置。當(dāng)有多個線程調(diào)用await()方法而進入等待狀態(tài)時,這幾個線程都將等待在此處。

總結(jié)

本文對JUC的工具類CountDownLatch進行詳細(xì)的講解,如有疑問請隨時反饋。

到此這篇關(guān)于JUC系列學(xué)習(xí)工具類CountDownLatch詳解的文章就介紹到這了,更多相關(guān)JUC工具類CountDownLatch 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

南华县| 桂阳县| 汉源县| 梁河县| 正镶白旗| 宜兴市| 景泰县| 田阳县| 沈阳市| 静宁县| 石林| 乐陵市| 梁河县| 吉隆县| 平阴县| 镇远县| 嘉义县| 高邮市| 安仁县| 汉寿县| 和田县| 东乡| 丰宁| 霍州市| 浑源县| 芦溪县| 许昌市| 旺苍县| 蒙阴县| 庄河市| 陇川县| 乐昌市| 息烽县| 林西县| 凌源市| 固镇县| 五常市| 辽源市| 渝中区| 辉县市| 杭州市|