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

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ù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JAVA_基本LDAP操作實例

    JAVA_基本LDAP操作實例

    這篇文章介紹了JAVA_基本LDAP操作實例,有需要的朋友可以參考一下
    2013-09-09
  • Java線程中斷的本質(zhì)深入理解

    Java線程中斷的本質(zhì)深入理解

    Java的中斷是一種協(xié)作機制。也就是說調(diào)用線程對象的interrupt方法并不一定就中斷了正在運行的線程,它只是要求線程自己在合適的時機中斷自己,本文將詳細介紹,需要了解的朋友可以參考下
    2012-12-12
  • springboot項目打docker鏡像實例(入門級)

    springboot項目打docker鏡像實例(入門級)

    最近做個項目,我們想把自己的程序打包成鏡像,并運行在docker容器中,本文主要介紹了springboot項目打docker鏡像實例,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • java小數(shù)位的例子

    java小數(shù)位的例子

    在java中要保留數(shù)字小數(shù)位我們有常用的四種方法,分別為:四舍五入,DecimalFormat,format,String .format與struts標簽操作實現(xiàn),下面給出例子
    2013-11-11
  • springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構建)

    springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構建)

    這篇文章主要介紹了springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構建),需要的朋友可以參考下
    2020-08-08
  • Java線程休眠_動力節(jié)點Java學院整理

    Java線程休眠_動力節(jié)點Java學院整理

    sleep() 的作用是讓當前線程休眠,即當前線程會從“運行狀態(tài)”進入到“休眠(阻塞)狀態(tài)”。下面通過實例代碼給大家介紹Java線程休眠的知識,需要的朋友參考下吧
    2017-05-05
  • 在SpringMVC框架下實現(xiàn)文件的上傳和下載示例

    在SpringMVC框架下實現(xiàn)文件的上傳和下載示例

    本篇文章主要介紹了在SpringMVC框架下實現(xiàn)文件的上傳和下載示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • java 從int數(shù)組中獲取最大數(shù)的方法

    java 從int數(shù)組中獲取最大數(shù)的方法

    這篇文章主要介紹了java 從int數(shù)組中獲取最大數(shù)的方法,需要的朋友可以參考下
    2017-02-02
  • Java使用Apache Commons高效處理CSV文件的操作指南

    Java使用Apache Commons高效處理CSV文件的操作指南

    在 Java 開發(fā)中,CSV(Comma-Separated Values,逗號分隔值)是一種常見的數(shù)據(jù)存儲格式,廣泛用于數(shù)據(jù)交換和簡單的存儲任務,本文將介紹Java使用Apache Commons高效處理CSV文件的操作指南,需要的朋友可以參考下
    2025-03-03
  • pageHelper一對多分頁解決方案示例

    pageHelper一對多分頁解決方案示例

    這篇文章主要為大家介紹了pageHelper一對多分頁解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04

最新評論

建湖县| 灵川县| 和平区| 观塘区| 观塘区| 吴川市| 尚志市| 伊宁市| 富源县| 金堂县| 金堂县| 吉木萨尔县| 深泽县| 色达县| 沧源| 永顺县| 沧州市| 栾川县| 张掖市| 库伦旗| 泰来县| 濮阳市| 大理市| 宁国市| 永靖县| 渭源县| 阿鲁科尔沁旗| 中阳县| 邹城市| 滨海县| 浦城县| 桃源县| 米易县| 桐庐县| 宿迁市| 永康市| 裕民县| 兰州市| 万宁市| 铜鼓县| 应用必备|