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

Java并發(fā)工具類(lèi)之CountDownLatch詳解

 更新時(shí)間:2023年12月27日 09:01:22   作者:緣來(lái)如此09  
這篇文章主要介紹了Java并發(fā)工具類(lèi)之CountDownLatch詳解,CountDownLatch可以使一個(gè)獲多個(gè)線(xiàn)程等待其他線(xiàn)程各自執(zhí)行完畢后再執(zhí)行,CountDownLatch可以解決那些一個(gè)或者多個(gè)線(xiàn)程在執(zhí)行之前必須依賴(lài)于某些必要的前提業(yè)務(wù)先執(zhí)行的場(chǎng)景,需要的朋友可以參考下

CountDownLatch

1.概述

CountDownLatch可以使一個(gè)獲多個(gè)線(xiàn)程等待其他線(xiàn)程各自執(zhí)行完畢后再執(zhí)行。

CountDownLatch 定義了一個(gè)計(jì)數(shù)器,和一個(gè)阻塞隊(duì)列, 當(dāng)計(jì)數(shù)器的值遞減為0之前,阻塞隊(duì)列里面的線(xiàn)程處于掛起狀態(tài),當(dāng)計(jì)數(shù)器遞減到0時(shí)會(huì)喚醒阻塞隊(duì)列所有線(xiàn)程,這里的計(jì)數(shù)器是一個(gè)標(biāo)志,可以表示一個(gè)任務(wù)一個(gè)線(xiàn)程,也可以表示一個(gè)倒計(jì)時(shí)器,CountDownLatch可以解決那些一個(gè)或者多個(gè)線(xiàn)程在執(zhí)行之前必須依賴(lài)于某些必要的前提業(yè)務(wù)先執(zhí)行的場(chǎng)景。

2.常用方法

CountDownLatch(int count); //構(gòu)造方法,創(chuàng)建一個(gè)值為count 的計(jì)數(shù)器。
?
await();//阻塞當(dāng)前線(xiàn)程,將當(dāng)前線(xiàn)程加入阻塞隊(duì)列。
?
await(long timeout, TimeUnit unit);//在timeout的時(shí)間之內(nèi)阻塞當(dāng)前線(xiàn)程,時(shí)間一過(guò)則當(dāng)前線(xiàn)程可以執(zhí)行,
?
countDown();//對(duì)計(jì)數(shù)器進(jìn)行遞減1操作,當(dāng)計(jì)數(shù)器遞減至0時(shí),當(dāng)前線(xiàn)程會(huì)去喚醒阻塞隊(duì)列里的所有線(xiàn)程。

3.應(yīng)用

我們經(jīng)常會(huì)在一個(gè)接口中調(diào)用多個(gè)第三方接口,然后將結(jié)果返回,其實(shí)就可以通過(guò)CountDownLatch來(lái)實(shí)現(xiàn)

  public static void main(String[] args) {
        CountDownLatch count = new CountDownLatch(3);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((int)(Math.random()*1000));
                    System.out.println("獲取接口一的數(shù)據(jù)");
                    count.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((int)(Math.random()*1000));
                    System.out.println("獲取接口二的數(shù)據(jù)");
                    count.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((int)(Math.random()*1000));
                    System.out.println("獲取接口三的數(shù)據(jù)");
                    count.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        thread2.start();
        thread3.start();
        try {
            count.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("執(zhí)行成功");
    }

4.實(shí)現(xiàn)原理

(1)創(chuàng)建計(jì)數(shù)器

  public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);//創(chuàng)建同步隊(duì)列,并設(shè)置初始計(jì)數(shù)器值
    }

(2)Sync類(lèi)

可以看出該類(lèi)是繼承AQS的,所以CountDownLatch的實(shí)現(xiàn)大多都是通過(guò)AQS來(lái)實(shí)現(xiàn)

    private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;
        Sync(int count) {
            setState(count);
        }
        int getCount() {
            return getState();
        }
        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
        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;
            }
        }
    }

(3)await方法

當(dāng)我們調(diào)用countDownLatch.wait()的時(shí)候,會(huì)創(chuàng)建一個(gè)節(jié)點(diǎn),加入到AQS阻塞隊(duì)列,并同時(shí)把當(dāng)前線(xiàn)程掛起,其實(shí)就是調(diào)用共享模式下的鎖獲取,詳情看AQS文章

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

 在Sync類(lèi)重寫(xiě)的tryAcquireShared()方法中g(shù)etState()只有等于0才會(huì)獲取到鎖,所以當(dāng)countDownLatch待執(zhí)行的任務(wù)數(shù)大于0都會(huì)堵塞該線(xiàn)程直到所有任務(wù)都完成

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

AQS中觸發(fā)堵塞線(xiàn)程的源碼:

private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        //新建節(jié)點(diǎn)加入阻塞隊(duì)列
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                //獲得當(dāng)前節(jié)點(diǎn)pre節(jié)點(diǎn)
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);//返回鎖的state
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                //重組雙向鏈表,清空無(wú)效節(jié)點(diǎn),掛起當(dāng)前線(xiàn)程
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

(4)countDown()方法

當(dāng)我們調(diào)用countDownLatch.countDown()方法的時(shí)候,會(huì)對(duì)計(jì)數(shù)器進(jìn)行減1操作,AQS內(nèi)部是通過(guò)釋放鎖的方式,對(duì)state進(jìn)行減1操作,當(dāng)state=0的時(shí)候證明計(jì)數(shù)器已經(jīng)遞減完畢,此時(shí)會(huì)將AQS阻塞隊(duì)列里的節(jié)點(diǎn)線(xiàn)程全部喚醒。

public void countDown() {
        //遞減鎖重入次數(shù),當(dāng)state=0時(shí)喚醒所有阻塞線(xiàn)程
        sync.releaseShared(1);
    }
public final boolean releaseShared(int arg) {
        //遞減鎖的重入次數(shù)
        if (tryReleaseShared(arg)) {
            doReleaseShared();//喚醒隊(duì)列所有阻塞的節(jié)點(diǎn)
            return true;
        }
        return false;
    }
 private void doReleaseShared() {
        //喚醒所有阻塞隊(duì)列里面的線(xiàn)程
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {//節(jié)點(diǎn)是否在等待喚醒狀態(tài)
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))//修改狀態(tài)為初始
                        continue;
                    unparkSuccessor(h);//成功則喚醒線(xiàn)程
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

到此這篇關(guān)于Java并發(fā)工具類(lèi)之CountDownLatch詳解的文章就介紹到這了,更多相關(guān)CountDownLatch詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Eclipse 使用Maven構(gòu)建SpringMVC項(xiàng)目

    Eclipse 使用Maven構(gòu)建SpringMVC項(xiàng)目

    本文主要介紹在Eclipse下創(chuàng)建Maven項(xiàng)目構(gòu)建SpringMVC框架的過(guò)程,講解的比較詳細(xì),需要的朋友可以參考下。
    2016-06-06
  • Java中Spring使用Quartz任務(wù)調(diào)度定時(shí)器

    Java中Spring使用Quartz任務(wù)調(diào)度定時(shí)器

    本篇文章主要介紹了Java中Spring使用Quartz任務(wù)調(diào)度定時(shí)器,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-02-02
  • SpringBoot生成jar/war包的布局應(yīng)用

    SpringBoot生成jar/war包的布局應(yīng)用

    在 Spring Boot 中,"布局應(yīng)用"(Application Layout)指的是打包生成的可執(zhí)行 jar 或 war 文件中的內(nèi)容組織結(jié)構(gòu),本文給大家介紹了SpringBoot生成jar/war包的布局應(yīng)用,需要的朋友可以參考下
    2024-02-02
  • 詳解SSM框架下結(jié)合log4j、slf4j打印日志

    詳解SSM框架下結(jié)合log4j、slf4j打印日志

    本篇文章主要介紹了詳解SSM框架下結(jié)合log4j、slf4j打印日志,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • Java?CAS與JUC組件詳解

    Java?CAS與JUC組件詳解

    CAS是一種基于樂(lè)觀(guān)鎖的無(wú)鎖并發(fā)控制技術(shù),其核心邏輯可以概括為:“我認(rèn)為當(dāng)前值應(yīng)該是A,如果是,則更新為B;否則放棄或重試”,整個(gè)過(guò)程由硬件保證原子性,無(wú)需傳統(tǒng)鎖機(jī)制,本文給大家介紹Java?CAS與JUC組件的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2025-04-04
  • Java利用sort方法解決字符串排序

    Java利用sort方法解決字符串排序

    在日常的編程任務(wù)中,字符串排序是一個(gè)常見(jiàn)的需求,本文將介紹如何使用Java中的??List??接口和??Collections??工具類(lèi)來(lái)實(shí)現(xiàn)字符串排序,需要的朋友可以參考下
    2026-03-03
  • mybatis動(dòng)態(tài)拼接實(shí)現(xiàn)有條件的插入

    mybatis動(dòng)態(tài)拼接實(shí)現(xiàn)有條件的插入

    這篇文章主要介紹了mybatis動(dòng)態(tài)拼接實(shí)現(xiàn)有條件的插入,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java volatile的適用場(chǎng)景實(shí)例詳解

    Java volatile的適用場(chǎng)景實(shí)例詳解

    在本文里我們給大家整理了一篇關(guān)于Java volatile的適用場(chǎng)景實(shí)例內(nèi)容和知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)下。
    2019-08-08
  • SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法

    SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法

    這篇文章主要介紹了SpringMVC配置攔截器實(shí)現(xiàn)登錄控制的方法,SpringMVC讀取Cookie判斷用戶(hù)是否登錄,對(duì)每一個(gè)action都要進(jìn)行判斷,有興趣的可以了解一下。
    2017-03-03
  • Spring IOC相關(guān)注解運(yùn)用(上篇)

    Spring IOC相關(guān)注解運(yùn)用(上篇)

    這篇文章主要介紹了Spring?IOC相關(guān)注解的運(yùn)用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05

最新評(píng)論

苏尼特右旗| 江都市| 自治县| 高密市| 隆昌县| 平顺县| 彰化县| 景洪市| 遂溪县| 当涂县| 曲沃县| 左贡县| 赤城县| 甘孜县| 南陵县| 台中县| 鲁甸县| 瓮安县| 寻乌县| 万荣县| 武清区| 西藏| 涞水县| 盖州市| 桃园市| 柘城县| 濮阳市| 香港| 佛山市| 克东县| 定边县| 大邑县| 平谷区| 建瓯市| 个旧市| 和平区| 平远县| 石台县| 四会市| 唐海县| 饶阳县|