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

Java并發(fā)編程之鎖、并發(fā)容器、阻塞隊(duì)列與異步編程實(shí)戰(zhàn)代碼

 更新時(shí)間:2026年06月02日 08:54:08   作者:fengxin_rou  
這篇文章主要介紹了Java并發(fā)編程之鎖、并發(fā)容器、阻塞隊(duì)列與異步編程的相關(guān)資料,分別是ReentrantLock的靈活鎖機(jī)制、ConcurrentHashMap的高性能并發(fā)設(shè)計(jì)、BlockingQueue的生產(chǎn)者、消費(fèi)者模式及CompletableFuture的異步編程能力,需要的朋友可以參考下

前言

在多核 CPU 成為主流的今天,并發(fā)編程已成為后端開發(fā)者必備的核心技能。本文系統(tǒng)梳理 Java 并發(fā)編程中的鎖機(jī)制、并發(fā)容器、阻塞隊(duì)列與異步編程四大核心模塊,深入解析底層實(shí)現(xiàn)原理,結(jié)合實(shí)戰(zhàn)代碼幫助讀者掌握高并發(fā)場(chǎng)景下的技術(shù)選型與避坑策略。

一、顯式鎖 ReentrantLock 深度解析

1.1 ReentrantLock 與 synchronized 核心區(qū)別

synchronized是 Java 原生的隱式鎖,基于 JVM 實(shí)現(xiàn),自動(dòng)完成鎖的獲取與釋放;而ReentrantLock是 JDK 提供的顯式鎖,基于 AQS(AbstractQueuedSynchronizer)框架實(shí)現(xiàn),需要手動(dòng)控制加鎖與釋放。

對(duì)比維度

synchronized

ReentrantLock

實(shí)現(xiàn)層面

JVM 層面

JDK API 層面

鎖釋放

自動(dòng)釋放

必須手動(dòng) unlock ()

可中斷

不支持

支持 lockInterruptibly ()

可超時(shí)

不支持

支持 tryLock (timeout)

公平鎖

僅非公平

支持公平 / 非公平

條件變量

僅 1 個(gè)等待隊(duì)列

支持多個(gè) Condition

synchronized在 JDK6 后進(jìn)行了大量?jī)?yōu)化,包括偏向鎖、輕量級(jí)鎖、自旋鎖等,性能已大幅提升。但在需要靈活控制鎖行為的場(chǎng)景下,ReentrantLock 仍是首選。

1.2 可重入性實(shí)現(xiàn)原理

可重入鎖指同一個(gè)線程可以多次獲取同一把鎖而不會(huì)產(chǎn)生死鎖。ReentrantLock 通過(guò) AQS 的 state 狀態(tài)變量和 exclusiveOwnerThread 實(shí)現(xiàn)可重入。

當(dāng)線程首次獲取鎖時(shí),state 從 0 變?yōu)?1,并記錄當(dāng)前持有線程;當(dāng)同一線程再次獲取鎖時(shí),state 進(jìn)行累加;釋放鎖時(shí) state 遞減,直到 state 歸 0 才真正釋放鎖。

// ReentrantLock.NonfairSync.tryAcquire()核心邏輯
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        // 鎖空閑,CAS嘗試獲取
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        // 同一線程重入,state累加
        int nextc = c + acquires;
        if (nextc < 0) throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

可重入性避免了同一線程反復(fù)獲取鎖導(dǎo)致的死鎖,是遞歸調(diào)用場(chǎng)景的必備特性。

1.3 可中斷鎖實(shí)現(xiàn)原理

synchronized獲取鎖時(shí)不可中斷,線程會(huì)一直阻塞直到獲取鎖;ReentrantLock 通過(guò)lockInterruptibly()方法支持中斷響應(yīng)。

當(dāng)調(diào)用lockInterruptibly()時(shí),如果線程在等待隊(duì)列中被中斷,會(huì)直接拋出 InterruptedException,不再繼續(xù)等待鎖。這為取消阻塞操作提供了可能,是實(shí)現(xiàn)超時(shí)獲取鎖的基礎(chǔ)。

public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}

// AQS.acquireInterruptibly()
public final void acquireInterruptibly(int arg) throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    if (!tryAcquire(arg))
        doAcquireInterruptibly(arg); // 可中斷的等待邏輯
}

1.4 可超時(shí)獲取鎖實(shí)現(xiàn)原理

tryLock(long timeout, TimeUnit unit)方法支持在指定時(shí)間內(nèi)嘗試獲取鎖,超時(shí)則返回 false。其實(shí)現(xiàn)基于 LockSupport.parkNanos () 進(jìn)行限時(shí)等待,在等待過(guò)程中同時(shí)檢測(cè)中斷和超時(shí)。

// 超時(shí)獲取鎖使用示例
public boolean tryLockWithTimeout(ReentrantLock lock, long timeoutMs) {
    try {
        return lock.tryLock(timeoutMs, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        return false;
    }
}

可超時(shí)特性在分布式系統(tǒng)中尤為重要,可以有效避免因網(wǎng)絡(luò)波動(dòng)導(dǎo)致的線程永久阻塞。

1.5 公平鎖與非公平鎖實(shí)現(xiàn)原理

ReentrantLock 默認(rèn)采用非公平鎖,可通過(guò)構(gòu)造函數(shù)參數(shù)指定為公平鎖:

ReentrantLock fairLock = new ReentrantLock(true);    // 公平鎖
ReentrantLock unfairLock = new ReentrantLock(false); // 非公平鎖(默認(rèn))

公平鎖嚴(yán)格按照線程請(qǐng)求順序分配鎖,新線程必須加入等待隊(duì)列尾部;非公平鎖允許新線程在鎖釋放時(shí)直接嘗試搶占,不考慮隊(duì)列中等待的線程。

公平鎖的tryAcquire()會(huì)額外檢查hasQueuedPredecessors(),確保只有等待隊(duì)列中沒(méi)有前驅(qū)節(jié)點(diǎn)時(shí)才嘗試獲取鎖。

非公平鎖性能通常優(yōu)于公平鎖(吞吐量高約 30%),但可能產(chǎn)生線程饑餓。公平鎖保證了順序性,但增加了上下文切換開銷。

1.6 實(shí)戰(zhàn)代碼示例

/**
 * ReentrantLock完整使用示例
 */
public class ReentrantLockDemo {
    private final ReentrantLock lock = new ReentrantLock(true);
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Queue<Integer> queue = new LinkedList<>();
    private static final int CAPACITY = 10;

    public void produce(int data) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == CAPACITY) {
                notFull.await(); // 隊(duì)列滿,生產(chǎn)者等待
            }
            queue.offer(data);
            notEmpty.signal(); // 喚醒消費(fèi)者
        } finally {
            lock.unlock(); // 必須在finally中釋放鎖
        }
    }

    public int consume() throws InterruptedException {
        lock.lockInterruptibly(); // 可中斷方式獲取鎖
        try {
            while (queue.isEmpty()) {
                notEmpty.await();
            }
            int data = queue.poll();
            notFull.signal();
            return data;
        } finally {
            lock.unlock();
        }
    }
}

注意事項(xiàng)

  • unlock()必須放在 finally 塊中,防止異常導(dǎo)致鎖泄漏

  • 使用多個(gè) Condition 可以精確控制喚醒條件,這是 synchronized 不具備的能力

二、ConcurrentHashMap 底層原理與演進(jìn)

2.1 JDK7 分段鎖設(shè)計(jì)原理

JDK7 的 ConcurrentHashMap 采用 \\ 分段鎖(Segment)\\ 設(shè)計(jì),整個(gè)哈希表被拆分為 16 個(gè) Segment 數(shù)組,每個(gè) Segment 獨(dú)立加鎖。

核心數(shù)據(jù)結(jié)構(gòu):

ConcurrentHashMap
└── Segment[] (默認(rèn)16個(gè))
    └── HashEntry[] (每個(gè)Segment獨(dú)立的哈希表)
        └── HashEntry鏈表

Segment 繼承自 ReentrantLock,每次 put 操作只鎖定對(duì)應(yīng)的 Segment,其他 Segment 的讀寫不受影響。理論上最大并發(fā)度等于 Segment 數(shù)量(默認(rèn) 16)。

但分段鎖存在明顯缺陷:

  1. 并發(fā)度固定,無(wú)法隨數(shù)組擴(kuò)容動(dòng)態(tài)提升

  2. 空間浪費(fèi),每個(gè) Segment 都需要獨(dú)立的鎖和數(shù)據(jù)結(jié)構(gòu)

  3. 跨段操作(如 size ())需要加鎖所有 Segment,性能較差

2.2 JDK8 架構(gòu)演進(jìn):CAS + synchronized

JDK8 徹底放棄分段鎖,采用數(shù)組 + 鏈表 + 紅黑樹結(jié)構(gòu),與 HashMap 保持一致。鎖的粒度從 Segment 級(jí)別細(xì)化到每個(gè)哈希桶(Node)級(jí)別。

核心改進(jìn):

  • 使用synchronized替代 ReentrantLock,JVM 對(duì) synchronized 的優(yōu)化更成熟

  • 無(wú)鎖競(jìng)爭(zhēng)時(shí)使用 CAS 進(jìn)行無(wú)鎖化更新

  • 僅在哈希桶發(fā)生哈希沖突時(shí)才對(duì)首節(jié)點(diǎn)加鎖

  • 鏈表長(zhǎng)度超過(guò) 8 時(shí)自動(dòng)轉(zhuǎn)為紅黑樹,解決哈希碰撞攻擊

// JDK8 ConcurrentHashMap.putVal()核心邏輯
final V putVal(K key, V value, boolean onlyIfAbsent) {
    int hash = spread(key.hashCode());
    for (Node<K,V>[] tab = table;;) {
        int i = (n - 1) & hash;
        Node<K,V> f = tabAt(tab, i);
        
        if (f == null) {
            // 桶為空,CAS直接插入
            if (casTabAt(tab, i, null, new Node(hash, key, value)))
                break;
        } else {
            synchronized (f) { // 僅鎖定桶的首節(jié)點(diǎn)
                if (tabAt(tab, i) == f) { // 雙重檢查
                    // 鏈表或紅黑樹插入邏輯
                }
            }
        }
    }
}

2.3 放棄分段鎖的深層原因

JDK8 放棄分段鎖主要基于以下考量:

1. 鎖粒度更細(xì)

  • 分段鎖最小粒度是 Segment,JDK8 最小粒度是哈希桶

  • 并發(fā)度隨數(shù)組容量動(dòng)態(tài)提升,理論最大并發(fā)度等于數(shù)組長(zhǎng)度

2. synchronized 性能優(yōu)化

  • JDK6 后 synchronized 引入偏向鎖、輕量級(jí)鎖、自適應(yīng)自旋

  • 無(wú)鎖競(jìng)爭(zhēng)時(shí)偏向鎖性能優(yōu)于 ReentrantLock

  • JVM 可以對(duì) synchronized 進(jìn)行逃逸分析等深度優(yōu)化

3. 減少內(nèi)存開銷

  • 消除 Segment 對(duì)象的內(nèi)存占用

  • 數(shù)據(jù)結(jié)構(gòu)與 HashMap 統(tǒng)一,代碼復(fù)用性更高

4. 紅黑樹引入

  • 解決哈希碰撞導(dǎo)致的鏈表過(guò)長(zhǎng)問(wèn)題

  • 極端情況下時(shí)間復(fù)雜度從 O (n) 降至 O (logn)

2.4 擴(kuò)容機(jī)制深度解析

ConcurrentHashMap 的擴(kuò)容是并發(fā)協(xié)作式的,支持多線程共同參與擴(kuò)容,這是其核心亮點(diǎn)。

擴(kuò)容觸發(fā)條件

  • 元素?cái)?shù)量達(dá)到閾值(容量 × 加載因子)

  • 單桶鏈表長(zhǎng)度超過(guò) 8 但數(shù)組容量小于 64

擴(kuò)容核心流程

  1. 擴(kuò)容準(zhǔn)備:創(chuàng)建 nextTable,容量為原數(shù)組 2 倍

  2. 擴(kuò)容標(biāo)記:sizeCtl 設(shè)為負(fù)數(shù),標(biāo)記正在擴(kuò)容

  3. 任務(wù)分配:每個(gè)線程負(fù)責(zé)連續(xù)的 16 個(gè)桶的遷移

  4. 并發(fā)遷移

    1. 處理完的桶設(shè)置為 ForwardingNode

    2. 遇到 ForwardingNode 自動(dòng)跳過(guò)或協(xié)助擴(kuò)容

  5. 擴(kuò)容完成:table 指向 nextTable,重置 sizeCtl

// 擴(kuò)容時(shí)的ForwardingNode標(biāo)記
static final class ForwardingNode<K,V> extends Node<K,V> {
    final Node<K,V>[] nextTable;
    ForwardingNode(Node<K,V>[] tab) {
        super(MOVED, null, null, null);
        this.nextTable = tab;
    }
}

并發(fā)擴(kuò)容的精妙之處

  • 讀操作遇到 ForwardingNode 會(huì)轉(zhuǎn)發(fā)到新數(shù)組,不阻塞

  • 寫操作遇到 ForwardingNode 會(huì)主動(dòng)協(xié)助擴(kuò)容,實(shí)現(xiàn) "多線程幫忙"

  • 遷移過(guò)程采用 "復(fù)制 + 清除" 方式,保證數(shù)據(jù)一致性

2.5 完整工作流程梳理

以 put 操作為例,完整執(zhí)行流程:

  1. 計(jì)算 key 的哈希值,定位哈希桶位置

  2. 如果數(shù)組未初始化,CAS 觸發(fā)初始化

  3. 如果目標(biāo)桶為空,CAS 直接插入新節(jié)點(diǎn)

  4. 如果遇到 ForwardingNode,協(xié)助擴(kuò)容后重試

  5. 否則,對(duì)桶首節(jié)點(diǎn)加 synchronized 鎖

  6. 遍歷鏈表或紅黑樹,key 存在則更新,不存在則追加

  7. 鏈表長(zhǎng)度超過(guò) 8,觸發(fā)樹化或擴(kuò)容

  8. 釋放鎖,CAS 更新元素計(jì)數(shù),檢查是否需要擴(kuò)容

整個(gè)過(guò)程中,鎖的持有時(shí)間極短,大部分操作都是無(wú)鎖的 CAS 操作,這是 ConcurrentHashMap 高性能的根本原因。

三、BlockingQueue 阻塞隊(duì)列實(shí)戰(zhàn)

3.1 阻塞隊(duì)列核心作用

BlockingQueue是 Java 并發(fā)包中最重要的數(shù)據(jù)結(jié)構(gòu)之一,專門解決生產(chǎn)者 - 消費(fèi)者模式的線程協(xié)作問(wèn)題。

核心特性:

  • 隊(duì)列滿時(shí),生產(chǎn)者線程自動(dòng)阻塞,直到有消費(fèi)者消費(fèi)

  • 隊(duì)列空時(shí),消費(fèi)者線程自動(dòng)阻塞,直到有生產(chǎn)者生產(chǎn)

  • 所有操作都是線程安全的,內(nèi)部通過(guò)鎖和條件變量實(shí)現(xiàn)

四種核心操作模式:

操作方式

拋出異常

返回特殊值

阻塞等待

超時(shí)等待

插入

add(e)

offer(e)

put(e)

offer(e, time, unit)

移除

remove()

poll()

take()

poll(time, unit)

檢查

element()

peek()

-

-

阻塞隊(duì)列是線程池的核心組件,也是解耦生產(chǎn)消費(fèi)速率不匹配的標(biāo)準(zhǔn)解決方案。

3.2 ArrayBlockingQueue 詳解

ArrayBlockingQueue是基于數(shù)組實(shí)現(xiàn)的有界阻塞隊(duì)列,創(chuàng)建時(shí)必須指定容量。

核心特點(diǎn):

  • 有界隊(duì)列,容量固定不可擴(kuò)容

  • 單鎖雙 Condition 機(jī)制(notEmpty + notFull)

  • 支持公平 / 非公平模式

  • 讀寫共用同一把鎖,并發(fā)度較低

// ArrayBlockingQueue核心結(jié)構(gòu)
public class ArrayBlockingQueue<E> {
    final Object[] items;      // 存儲(chǔ)數(shù)組
    int takeIndex;             // 取元素位置
    int putIndex;              // 放元素位置
    int count;                 // 元素?cái)?shù)量
    final ReentrantLock lock;  // 單鎖
    private final Condition notEmpty;
    private final Condition notFull;
}

適用場(chǎng)景:隊(duì)列大小可預(yù)估、對(duì)內(nèi)存占用敏感的場(chǎng)景。

3.3 LinkedBlockingQueue 詳解

LinkedBlockingQueue是基于鏈表實(shí)現(xiàn)的阻塞隊(duì)列,默認(rèn)容量為 Integer.MAX_VALUE。

核心特點(diǎn):

  • 雙鎖分離設(shè)計(jì)(takeLock + putLock),讀寫互不阻塞

  • 默認(rèn)無(wú)界(實(shí)際最大 2^31-1),也可指定容量

  • 吞吐量高于 ArrayBlockingQueue

  • 內(nèi)存占用相對(duì)較高

// LinkedBlockingQueue雙鎖設(shè)計(jì)
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();

注意:無(wú)界模式下如果生產(chǎn)速度遠(yuǎn)大于消費(fèi)速度,可能導(dǎo)致 OOM。

適用場(chǎng)景:生產(chǎn)消費(fèi)速率差異較大、追求高吞吐量的場(chǎng)景。

3.4 SynchronousQueue 詳解

SynchronousQueue是一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列,每個(gè)插入操作必須等待另一個(gè)線程的移除操作。

核心特點(diǎn):

  • 內(nèi)部沒(méi)有緩沖區(qū),隊(duì)列容量始終為 0

  • 支持公平 / 非公平模式

  • 直接傳遞,不存儲(chǔ)元素

  • 是 Executors.newCachedThreadPool () 的默認(rèn)隊(duì)列

// SynchronousQueue典型用法
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
// 生產(chǎn)者線程
new Thread(() -> {
    queue.put(1); // 會(huì)阻塞直到有消費(fèi)者take
}).start();
// 消費(fèi)者線程
new Thread(() -> {
    queue.take(); // 會(huì)阻塞直到有生產(chǎn)者put
}).start();

適用場(chǎng)景:任務(wù)必須立即處理、不允許排隊(duì)的場(chǎng)景,如 CachedThreadPool。

3.5 DelayQueue 原理與延時(shí)任務(wù)應(yīng)用

DelayQueue是支持延時(shí)獲取元素的無(wú)界阻塞隊(duì)列,元素必須實(shí)現(xiàn) Delayed 接口。

核心原理:

  • 內(nèi)部基于 PriorityQueue 實(shí)現(xiàn),按過(guò)期時(shí)間排序

  • 只有當(dāng)元素的延遲時(shí)間到期后才能被取出

  • 隊(duì)首元素永遠(yuǎn)是最早過(guò)期的元素

// 延時(shí)任務(wù)元素定義
public class DelayedTask implements Delayed {
    private final long executeTime;
    private final Runnable task;

    public DelayedTask(long delayMs, Runnable task) {
        this.executeTime = System.currentTimeMillis() + delayMs;
        this.task = task;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed other) {
        return Long.compare(this.executeTime, ((DelayedTask)other).executeTime);
    }
}

典型應(yīng)用場(chǎng)景

  1. 訂單超時(shí)自動(dòng)取消

  2. 會(huì)話超時(shí)清理

  3. 定時(shí)任務(wù)調(diào)度

  4. 緩存過(guò)期失效

// 延時(shí)隊(duì)列使用示例
DelayQueue<DelayedTask> delayQueue = new DelayQueue<>();
delayQueue.put(new DelayedTask(30000, () -> System.out.println("30秒后執(zhí)行")));
delayQueue.put(new DelayedTask(60000, () -> System.out.println("60秒后執(zhí)行")));

// 消費(fèi)者線程
while (true) {
    DelayedTask task = delayQueue.take(); // 阻塞直到任務(wù)到期
    task.run();
}

3.6 四者對(duì)比與選型建議

特性

ArrayBlockingQueue

LinkedBlockingQueue

SynchronousQueue

DelayQueue

容量

有界

可選有界 / 無(wú)界

0

無(wú)界

數(shù)據(jù)結(jié)構(gòu)

數(shù)組

鏈表

直接傳遞

優(yōu)先級(jí)隊(duì)列

鎖機(jī)制

單鎖

雙鎖分離

CAS

單鎖

公平性

支持

不支持

支持

不支持

吞吐量

中等

極高

典型應(yīng)用

固定大小線程池

固定大小線程池

緩存線程池

延時(shí)任務(wù)

選型建議

  • 需要控制隊(duì)列大小 → ArrayBlockingQueue

  • 追求高吞吐量 → LinkedBlockingQueue

  • 任務(wù)必須立即執(zhí)行 → SynchronousQueue

  • 需要延時(shí)執(zhí)行 → DelayQueue

四、CompletableFuture 異步編程

4.1 異步編程背景

傳統(tǒng) Future 接口的局限性:

  • 無(wú)法手動(dòng)完成

  • 不支持鏈?zhǔn)秸{(diào)用

  • 不支持異常處理

  • 無(wú)法組合多個(gè) Future

CompletableFuture在 Java8 中引入,實(shí)現(xiàn)了 CompletionStage 接口,提供了豐富的異步編程能力,支持函數(shù)式編程風(fēng)格。

4.2 核心 API 分類詳解

1. 創(chuàng)建類 API

// 使用默認(rèn)線程池
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> System.out.println("異步任務(wù)"));
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "返回結(jié)果");

// 使用自定義線程池(推薦)
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "自定義線程池", executor);

// 手動(dòng)完成
CompletableFuture<String> future4 = new CompletableFuture<>();
future4.complete("手動(dòng)設(shè)置結(jié)果");
future4.completeExceptionally(new RuntimeException("手動(dòng)異常"));

注意:默認(rèn)使用 ForkJoinPool.commonPool (),所有 CompletableFuture 共享,CPU 密集型任務(wù)建議使用自定義線程池。

2. 鏈?zhǔn)睫D(zhuǎn)換類 API

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(s -> s + " World")           // 同步轉(zhuǎn)換
    .thenApplyAsync(s -> s.toUpperCase())   // 異步轉(zhuǎn)換
    .thenAccept(s -> System.out.println(s)) // 消費(fèi)結(jié)果
    .thenRun(() -> System.out.println("執(zhí)行完成")); // 僅執(zhí)行,不消費(fèi)結(jié)果
  • thenApply:輸入 T,輸出 U,類似 map

  • thenAccept:輸入 T,無(wú)輸出,消費(fèi)型

  • thenRun:無(wú)輸入無(wú)輸出,僅執(zhí)行動(dòng)作

3. 組合類 API

// AND組合:兩個(gè)都完成才執(zhí)行
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "World");

f1.thenCombine(f2, (s1, s2) -> s1 + " " + s2)
  .thenAccept(System.out::println); // 輸出 Hello World

// OR組合:任意一個(gè)完成就執(zhí)行
CompletableFuture<String> fast = f1.applyToEither(f2, s -> s + " faster");

4. 異常處理 API

CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("出錯(cuò)了");
    return "正常";
})
.exceptionally(ex -> {
    System.out.println("捕獲異常: " + ex.getMessage());
    return "默認(rèn)值"; // 異常時(shí)返回默認(rèn)值
})
.handle((result, ex) -> {
    if (ex != null) {
        return "處理異常";
    }
    return result;
})
.whenComplete((result, ex) -> {
    // 無(wú)論成功失敗都會(huì)執(zhí)行,不改變結(jié)果
    System.out.println("執(zhí)行完成");
});

5. 多任務(wù)組合

// 所有任務(wù)都完成
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);

// 任意一個(gè)任務(wù)完成
CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2, f3);

4.3 實(shí)戰(zhàn)示例:并行調(diào)用優(yōu)化

/**
 * 并行調(diào)用多個(gè)服務(wù),聚合結(jié)果
 */
public class CompletableFutureDemo {
    public UserInfo getUserInfo(Long userId) {
        // 并行調(diào)用三個(gè)接口
        CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> userService.getUser(userId));
        CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(() -> orderService.getOrders(userId));
        CompletableFuture<List<Address>> addrFuture = CompletableFuture.supplyAsync(() -> addressService.getAddresses(userId));

        // 等待所有完成,聚合結(jié)果
        return CompletableFuture.allOf(userFuture, orderFuture, addrFuture)
            .thenApply(v -> {
                UserInfo info = new UserInfo();
                info.setUser(userFuture.join());
                info.setOrders(orderFuture.join());
                info.setAddresses(addrFuture.join());
                return info;
            })
            .exceptionally(ex -> {
                log.error("獲取用戶信息失敗", ex);
                return null;
            })
            .join();
    }
}

通過(guò) CompletableFuture,原本串行 3 秒的調(diào)用可以優(yōu)化到 1 秒完成,這是微服務(wù)架構(gòu)下的常用優(yōu)化手段。

結(jié)語(yǔ)

本文系統(tǒng)解析了 Java 并發(fā)編程的四大核心模塊:ReentrantLock 的靈活鎖機(jī)制、ConcurrentHashMap 的高性能并發(fā)設(shè)計(jì)、BlockingQueue 的生產(chǎn)者 - 消費(fèi)者模式、CompletableFuture 的異步編程能力。

這些技術(shù)是構(gòu)建高并發(fā)系統(tǒng)的基石。建議結(jié)合實(shí)際項(xiàng)目深入實(shí)踐,重點(diǎn)關(guān)注各組件的適用場(chǎng)景與性能特性,避免在生產(chǎn)環(huán)境中出現(xiàn)并發(fā)安全問(wèn)題。進(jìn)階可深入研究 AQS 框架、JMM 內(nèi)存模型與無(wú)鎖算法。

到此這篇關(guān)于Java并發(fā)編程之鎖、并發(fā)容器、阻塞隊(duì)列與異步編程實(shí)戰(zhàn)代碼的文章就介紹到這了,更多相關(guān)Java并發(fā)編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中@RestControllerAdvice @ExceptionHandler異常統(tǒng)一處理類失效原因分析

    SpringBoot中@RestControllerAdvice @ExceptionHandler異常統(tǒng)一處

    這篇文章主要介紹了SpringBoot中@RestControllerAdvice @ExceptionHandler異常統(tǒng)一處理類失效原因,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java基礎(chǔ)篇之HashMap指定初始值

    Java基礎(chǔ)篇之HashMap指定初始值

    這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之HashMap指定初始值的相關(guān)資料,HashMap是Java中常用的數(shù)據(jù)結(jié)構(gòu),它提供了高效的鍵值對(duì)存儲(chǔ)和查詢功能,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • SpringBoot實(shí)現(xiàn)解析.mdb文件的實(shí)戰(zhàn)指南

    SpringBoot實(shí)現(xiàn)解析.mdb文件的實(shí)戰(zhàn)指南

    這篇文章主要為大家詳細(xì)介紹了如何在SpringBoot項(xiàng)目中解析舊版Microsoft Access的.mdb文件,文中提供完整的Maven依賴配置、核心工具類封裝及使用示例,幫助開發(fā)者快速完成遺留系統(tǒng)數(shù)據(jù)遷移,希望對(duì)大家有所幫助
    2026-02-02
  • IDEA強(qiáng)制清除Maven緩存的方法示例

    IDEA強(qiáng)制清除Maven緩存的方法示例

    這篇文章主要介紹了IDEA強(qiáng)制清除Maven緩存的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • APT?注解處理器實(shí)現(xiàn)?Lombok?常用注解功能詳解

    APT?注解處理器實(shí)現(xiàn)?Lombok?常用注解功能詳解

    這篇文章主要為大家介紹了使用APT?注解處理器實(shí)現(xiàn)?Lombok?常用注解功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • JAVA的發(fā)展前景如何好不好自學(xué)

    JAVA的發(fā)展前景如何好不好自學(xué)

    這篇文章主要介紹了JAVA的發(fā)展前景如何好不好自學(xué),很多朋友想自學(xué)java不知道好不好學(xué),能不能學(xué)會(huì),今天小編給大家分享一篇教程關(guān)于java的發(fā)展前景的文章,需要的朋友可以參考下
    2020-06-06
  • Springboot升級(jí)到2.7.2結(jié)合nacos遇到的坑及解決

    Springboot升級(jí)到2.7.2結(jié)合nacos遇到的坑及解決

    這篇文章主要介紹了Springboot升級(jí)到2.7.2結(jié)合nacos遇到的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • tomcat在Linux環(huán)境下的安裝與配置詳細(xì)教程

    tomcat在Linux環(huán)境下的安裝與配置詳細(xì)教程

    這篇文章主要介紹了tomcat在Linux環(huán)境下安裝與配置的相關(guān)資料,涵蓋Java環(huán)境準(zhǔn)備、下載解壓、啟動(dòng)服務(wù)、部署項(xiàng)目及管理界面設(shè)置,適合開發(fā)測(cè)試環(huán)境搭建,需要的朋友可以參考下
    2025-05-05
  • Java ArrayList與LinkedList及HashMap容器的用法區(qū)別

    Java ArrayList與LinkedList及HashMap容器的用法區(qū)別

    這篇文章主要介紹了Java ArrayList與LinkedList及HashMap容器的用法區(qū)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-07-07
  • 一篇文章帶你了解Java SpringBoot四大核心組件

    一篇文章帶你了解Java SpringBoot四大核心組件

    這篇文章主要介紹了SpringBoot四大核心組件的使用小結(jié),詳細(xì)的介紹了這方面的知識(shí),有興趣的可以了解一下,希望能夠給你帶來(lái)幫助
    2021-09-09

最新評(píng)論

施甸县| 南充市| 辉县市| 通山县| 临汾市| 探索| 武城县| 思南县| 金溪县| 广南县| 航空| 常德市| 南昌县| 礼泉县| 内黄县| 航空| 武义县| 宜城市| 鸡泽县| 武冈市| 石楼县| 渝北区| 承德县| 威海市| 亚东县| 多伦县| 安阳市| 湖口县| 宁河县| 古田县| 凌云县| 田东县| 闽侯县| 登封市| 科尔| 辛集市| 凤山县| 依安县| 临安市| 司法| 东丽区|