成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

沒看過ReentrantLock源碼,別說精通Java并發編程

開發 前端
看完了CountDownLatch的所有源碼,是不是覺得CountDownLatch邏輯很簡單。因為加鎖流程的編排工作已經在父類AQS中實現,子類只需要實現具體的加鎖邏輯即可,也就是實現tryReleaseShared()方法和tryAcquireShared()方法。而加鎖邏輯也很簡單,也就是修改同步狀態state的值即可。

引言

高手程序員與新手程序員一個簡單的判斷標準,就是有沒有使用過CountDownLatch,在互聯網公司工作超過3年的程序員基本上應該都用過。CountDownLatch中文名稱叫做閉鎖,也叫計數鎖,不過不是用來加鎖的,而是通過計數實現條件等待的功能。CountDownLatch的使用場景有兩個:

  1. 當前線程等待其他線程都執行完成之后,再執行。
  2. 所有線程滿足條件后,再一起執行。

使用示例

CountDownLatch常用的方法就兩個,countDown()方法用來將計數器減一,await()方法會阻塞當前線程,直到計數器值等于0。

場景1:

先看一下第一種場景,也是最常用的場景:

  • 當前線程等待其他線程都執行完成之后,再執行。

在工作中什么時候會遇到這種場景呢?比如當前線程需要查詢3個數據庫,并且把查詢結果匯總返回給前端。查詢3個數據庫的邏輯,可以分別使用3個線程加快查詢速度。但是怎么判斷3個線程都執行結束了呢?這時候就可以使用CountDownLatch了。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 一燈架構
 * @apiNote CountDownLatch測試類(場景1)
 **/
public class CountDownLatchTest1 {

    public static void main(String[] args) throws InterruptedException {

        // 1. 創建一個線程池,用來執行3個查詢任務
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 2. 創建一個計數鎖,數量是3
        CountDownLatch countDownLatch = new CountDownLatch(3);

        // 3. 啟動3個查詢任務
        for (int i = 0; i < 3; i++) {
            executorService.submit(() -> {
                try {
                    // 4. 睡眠1秒,模擬任務執行過程
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + " 執行完成");
                    // 5. 任務執行完成,計數器減一
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                }
            });
        }

        // 6. 等待所有任務執行完成
        countDownLatch.await();
        System.out.println("所有任務執行完成。");

        // 7. 關閉線程池
        executorService.shutdown();
    }
}

輸出結果:

pool-1-thread-2 執行完成 pool-1-thread-1 執行完成 pool-1-thread-3 執行完成 所有任務執行完成。

需要注意的是,這里創建CountDownLatch計數器的時候,指定的數量是3,因為有3個任務。在3個任務沒有執行完成之前,await()方法會一直阻塞,直到3個任務都執行完成。

場景2

再看一下第二種場景,有些情況用的也比較多:

  • 所有線程滿足條件后,再一起執行。

什么情況下會遇到這種場景呢?比如系統中多個任務線程存在先后依賴關系,必須等待其他線程啟動完成后,才能一起執行。

/**
 * @author 一燈架構
 * @apiNote CountDownLatch測試類(場景2)
 **/
public class CountDownLatchTest {

    public static void main(String[] args) throws InterruptedException {

        // 1. 創建一個線程池,用來執行3個任務
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 2. 創建一個計數鎖,數量是1
        CountDownLatch countDownLatch = new CountDownLatch(1);

        // 3. 啟動3個任務
        for (int i = 0; i < 3; i++) {
            executorService.submit(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 啟動完成");
                    // 4. 等待其他任務啟動完成
                    countDownLatch.await();
                    // 5. 睡眠1秒,模擬任務執行過程
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + " 執行完成");
                } catch (InterruptedException e) {
                }
            });
        }

        // 6. 所有任務啟動完成,計數器減一
        countDownLatch.countDown();
        System.out.println("所有任務啟動完成,開始執行。");

        // 7. 關閉線程池
        executorService.shutdown();
    }
}

輸出結果:

pool-1-thread-1 啟動完成 pool-1-thread-2 啟動完成 pool-1-thread-3 啟動完成 所有任務啟動完成,開始執行。 pool-1-thread-1 執行完成 pool-1-thread-3 執行完成 pool-1-thread-2 執行完成

需要注意的是,與場景1不同,這里創建CountDownLatch計數器的時候,指定的數量是1,因為3個任務需要滿足同一個條件,就是都啟動完成,也就是只需要調用一次countDown()方法。 看完了CountDownLatch的使用方式,再看一下CountDownLatch的源碼實現。

類屬性

public class CountDownLatch {

    // 只有一個Sync同步變量
    private final Sync sync;

    // Sync繼承自AQS,主要邏輯都在這里面
    private static final class Sync extends AbstractQueuedSynchronizer {

        // 只有這一個構造方法,需要指定計數器數值
        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

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

        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

}

跟ReentrantLock一樣,CountDownLatch也沒有直接繼承AQS,也是采用組合的方式,使用Sync同步變量實現計數的功能,而Sync同步變量才是真正繼承AQS的。

countDown方法源碼

public void countDown() {
    // 底層調用父類AQS中的releaseShared()方法
    sync.releaseShared(1);
}

countDown()方法里面調用的是父類AQS中的releaseShared()方法,而releaseShared()方法又在調用子類Sync中tryReleaseShared()方法。

/**
 * 父類AQS
 */
public abstract class AbstractQueuedSynchronizer
        extends AbstractOwnableSynchronizer
        implements java.io.Serializable {
            
    public final boolean releaseShared(int arg) {
        // tryReleaseShared()由子類實現
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

    // 定義抽象方法,由子類實現
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }
}
/**
 * 子類Sync
 */
private static final class Sync extends AbstractQueuedSynchronizer {
    
    // 實現父類AQS中的tryReleaseShared()方法
    @Override
    protected boolean tryReleaseShared(int releases) {
        for (;;) {
            int c = getState();
            if (c == 0) {
                return false;
            }
            int nextc = c-1;
            if (compareAndSetState(c, nextc)) {
                return nextc == 0;
            }
        }
    }
}

而Sync同步類中tryReleaseShared()方法邏輯也很簡單,就是把同步狀態state值減一。

await源碼

await()方法底層也是調用父類中acquireSharedInterruptibly()方法,而父類AQS又需要調用子類Sync中的具體實現。

public void await() throws InterruptedException {
    // 底層調用父類AQS中的releaseShared()方法
    sync.acquireSharedInterruptibly(1);
}
/**
 * 父類AQS
 */
public abstract class AbstractQueuedSynchronizer
        extends AbstractOwnableSynchronizer
        implements java.io.Serializable {

    public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        // tryAcquireShared()由子類實現
        if (tryAcquireShared(arg) < 0) {
            doAcquireSharedInterruptibly(arg);
        }
    }

    // 定義抽象方法,由子類實現
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

}

子類Sync只需要實現tryAcquireShared()方法即可,而tryAcquireShared()方法的作用就是判斷鎖是否已經完全釋放,即同步狀態state=0。

/**
 * 子類Sync
 */
private static final class Sync extends AbstractQueuedSynchronizer {

    // 實現父類AQS中的tryAcquireShared()方法
    @Override
    protected int tryAcquireShared(int acquires) {
        return (getState() == 0) ? 1 : -1;
    }
}

總結

看完了CountDownLatch的所有源碼,是不是覺得CountDownLatch邏輯很簡單。

因為加鎖流程的編排工作已經在父類AQS中實現,子類只需要實現具體的加鎖邏輯即可,也就是實現tryReleaseShared()方法和tryAcquireShared()方法。而加鎖邏輯也很簡單,也就是修改同步狀態state的值即可。想要詳細了解父類AQS的流程,可以翻看前幾篇文章。

下篇文章再一塊學習一下共享鎖Semaphore的源碼實現。

責任編輯:武曉燕 來源: 一燈架構
相關推薦

2024-02-29 09:37:25

Java并發編程

2023-12-28 07:49:11

線程池源碼應用場景

2023-04-06 00:15:03

JavaReentrantL線程

2023-09-12 13:48:47

2019-09-02 08:08:30

緩存HTTP數據庫

2024-04-29 09:06:46

線程初始化源碼

2015-09-22 13:08:42

戴爾云計算

2020-11-16 08:11:32

ReentrantLo

2023-05-23 08:54:43

SRESLO運營

2017-09-19 14:53:37

Java并發編程并發代碼設計

2021-09-01 17:51:53

技術LinkedList 源碼

2020-08-24 08:13:25

非公平鎖源碼

2022-11-14 11:09:36

源碼AQS加鎖

2011-12-29 13:31:15

Java

2025-02-17 00:00:25

Java并發編程

2025-02-19 00:05:18

Java并發編程

2025-06-18 08:10:00

Java并發編程開發

2021-09-02 09:53:42

開發Redis配置

2022-11-27 08:12:11

RocketMQ源碼工具類

2020-01-22 16:29:52

機器學習人工智能計算機
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99久久中文字幕三级久久日本 | 久久久久综合 | 91免费电影 | 日韩在线小视频 | 欧美日韩国产一区二区三区 | www国产成人免费观看视频,深夜成人网 | 久久99视频免费观看 | 国产精品久久久一区二区三区 | 中文字幕第二区 | 午夜影院操 | 国产精品不卡 | 日本欧美国产在线观看 | 精品九九久久 | 国产精品久久久久久中文字 | 国产三级日本三级 | 日本欧美国产在线观看 | 成人在线小视频 | 91亚洲精| 欧美激情一区二区三区 | 国产精品日韩在线观看一区二区 | 特黄色一级毛片 | 国精日本亚洲欧州国产中文久久 | 日韩高清中文字幕 | 久久只有精品 | 大陆一级毛片免费视频观看 | 国产精品久久二区 | 国产精品久久久久久久久久软件 | 福利色导航 | 手机日韩 | 久久在线精品 | 欧美一区二区免费在线 | 午夜精品一区二区三区在线观看 | 在线亚洲免费视频 | 成年网站在线观看 | 男人av的天堂 | 精品福利一区二区三区 | 日韩成人在线一区 | 成人精品在线视频 | 男人天堂999| 日韩精品一区二区三区高清免费 | 久热国产精品 |