欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JUC系列學習工具類CountDownLatch詳解

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

前言:

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

Join 解決方案

join 的工作原理是,檢查thread是否存活,如果存活則讓當前線程永遠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í)行結果

從結果中,我們可以看出只有子線程執(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í)行任務");
        Thread.sleep(300);
    }
}

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

執(zhí)行結果:

原理說明

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

基本原理

CountDownLatch

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

常用的方法

countDown:用于使計數(shù)器減一,其一般是執(zhí)行任務的線程調(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,如果是則將其設置為nextc(自減1),如果state不為c,則說明有另外的線程在getState()方法和compareAndSetState()方法調(diào)用之間對state進行了設置,當前線程也就沒有成功設置state屬性的值,其會進入下一次循環(huán)中,如此往復,直至其成功設置state屬性的值,即countDown()方法調(diào)用成功。

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

說明:首先判斷頭結點不為空,且不為尾節(jié)點,說明等待隊列中有等待喚醒的線程,這里需要說明的是,在等待隊列中,頭節(jié)點中并沒有保存正在等待的線程,其只是一個空的Node對象,真正等待的線程是從頭節(jié)點的下一個節(jié)點開始存放的,因而會有對頭結點是否等于尾節(jié)點的判斷。在判斷等待隊列中有正在等待的線程之后,其會清除頭結點的狀態(tài)信息,并且調(diào)用unparkSuccessor(Node)方法喚醒頭結點的下一個節(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)方法中,首先使用當前線程創(chuàng)建一個共享模式的節(jié)點。然后在一個for循環(huán)中判斷當前線程是否獲取到執(zhí)行權限,如果有(r >= 0判斷)則將當前節(jié)點設置為頭節(jié)點,并且喚醒后續(xù)處于共享模式的節(jié)點;如果沒有,則對調(diào)用shouldParkAfterFailedAcquire(Node, Node)和parkAndCheckInterrupt()方法使當前線程處于"擱置"狀態(tài),該"擱置"狀態(tài)是由操作系統(tǒng)進行的,這樣可以避免該線程無限循環(huán)而獲取不到執(zhí)行權限,造成資源浪費,這里也就是線程處于等待狀態(tài)的位置,也就是說當線程被阻塞的時候就是阻塞在這個位置。當有多個線程調(diào)用await()方法而進入等待狀態(tài)時,這幾個線程都將等待在此處。

總結

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

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

相關文章

  • Linux系統(tǒng)下更換jdk版本詳細步驟

    Linux系統(tǒng)下更換jdk版本詳細步驟

    隨著Java語言的不斷更新,多個版本的JDK在現(xiàn)在的Linux環(huán)境中都存在,使得不同的開發(fā)人員可以按照自己的需求使用不同的JDK版本,這篇文章主要給大家介紹了關于Linux系統(tǒng)下更換jdk版本的詳細步驟,需要的朋友可以參考下
    2023-12-12
  • SpringBoot雪花算法主鍵ID傳到前端后精度丟失問題的解決

    SpringBoot雪花算法主鍵ID傳到前端后精度丟失問題的解決

    本文主要介紹了SpringBoot雪花算法主鍵ID傳到前端后精度丟失問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • SpringBoot框架實現(xiàn)切換啟動開發(fā)環(huán)境和測試環(huán)境

    SpringBoot框架實現(xiàn)切換啟動開發(fā)環(huán)境和測試環(huán)境

    這篇文章主要介紹了SpringBoot框架實現(xiàn)切換啟動開發(fā)環(huán)境和測試環(huán)境,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java鎖的升級策略 偏向鎖 輕量級鎖 重量級鎖

    Java鎖的升級策略 偏向鎖 輕量級鎖 重量級鎖

    在本文中小編給的大家整理了關于Java鎖的升級策略 偏向鎖 輕量級鎖 重量級鎖的相關知識點內(nèi)容,需要的朋友們參考下。
    2019-06-06
  • spring boot 防止重復提交實現(xiàn)方法詳解

    spring boot 防止重復提交實現(xiàn)方法詳解

    這篇文章主要介紹了spring boot 防止重復提交實現(xiàn)方法,結合實例形式詳細分析了spring boot 防止重復提交具體配置、實現(xiàn)方法及操作注意事項,需要的朋友可以參考下
    2019-11-11
  • springboot3請求參數(shù)種類及接口測試案例小結

    springboot3請求參數(shù)種類及接口測試案例小結

    這篇文章主要介紹了springboot3請求參數(shù)種類及接口測試案例小結,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-10-10
  • 攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼

    攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼

    這篇文章主要介紹了攔截JSP頁面,校驗是否已登錄詳解及實現(xiàn)代碼的相關資料,需要的朋友可以參考下
    2016-11-11
  • Java的springcloud Sentinel是什么你知道嗎

    Java的springcloud Sentinel是什么你知道嗎

    這篇文章主要介紹了Java之springcloud Sentinel案例講解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java中Elasticsearch的核心概念詳解

    Java中Elasticsearch的核心概念詳解

    這篇文章主要介紹了Java中Elasticsearch的核心概念詳解,Elasticsearch 是一個分布式、免費和開放的搜索和分析引擎,適用于所有類型的數(shù)據(jù),包括文本、數(shù)字、地理空間、結構化和非結構化數(shù)據(jù),需要的朋友可以參考下
    2023-07-07
  • java判斷對象中某個屬性是否為空方法代碼

    java判斷對象中某個屬性是否為空方法代碼

    這篇文章主要給大家介紹了關于java判斷對象中某個屬性是否為空的相關資料,最近遇到后臺接收值的時候,需要對接收對象進行非空校驗,需要的朋友可以參考下
    2023-07-07

最新評論