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

Java 的 Condition 接口與等待通知機(jī)制詳解

 更新時(shí)間:2025年05月21日 14:46:14   作者:潛意識(shí)Java  
在 Java 并發(fā)編程里,實(shí)現(xiàn)線程間的協(xié)作與同步是極為關(guān)鍵的任務(wù),本文將深入探究Condition接口及其背后的等待通知機(jī)制,感興趣的朋友一起看看吧

一、引言

在 Java 并發(fā)編程里,實(shí)現(xiàn)線程間的協(xié)作與同步是極為關(guān)鍵的任務(wù)。除了使用 Object 類的 wait()、notify() 和 notifyAll() 方法實(shí)現(xiàn)簡(jiǎn)單的等待 - 通知機(jī)制外,Java 還提供了 Condition 接口,它與 ReentrantLock 配合使用,能實(shí)現(xiàn)更靈活、更精細(xì)的線程間通信。本文將深入探究 Condition 接口及其背后的等待通知機(jī)制。

二、Condition 接口概述

2.1 基本概念

Condition 接口位于 java.util.concurrent.locks 包中,它提供了類似 Object 類的 wait()、notify() 和 notifyAll() 方法的功能,但 Condition 更為強(qiáng)大和靈活。Condition 實(shí)例是通過(guò) Lock 對(duì)象的 newCondition() 方法創(chuàng)建的,每個(gè) Lock 對(duì)象可以創(chuàng)建多個(gè) Condition 實(shí)例,這使得我們可以針對(duì)不同的條件進(jìn)行線程的等待和喚醒操作。

2.2 與 Object 類等待通知方法的區(qū)別

  • 關(guān)聯(lián)對(duì)象不同Object 類的 wait()notify() 和 notifyAll() 方法必須在 synchronized 塊或方法中使用,它們關(guān)聯(lián)的是對(duì)象的內(nèi)部鎖;而 Condition 接口的方法(如 await()、signal() 和 signalAll())必須與 Lock 對(duì)象配合使用,關(guān)聯(lián)的是 Lock 對(duì)象。
  • 靈活性不同Condition 可以創(chuàng)建多個(gè)等待隊(duì)列,允許更細(xì)粒度的線程控制。例如,一個(gè)線程可以等待某個(gè)特定的條件,而另一個(gè)線程可以喚醒等待該條件的線程,而 Object 類的等待通知方法只能操作一個(gè)隱含的等待隊(duì)列。

三、Condition 接口的常用方法

3.1 await () 方法

await() 方法會(huì)使當(dāng)前線程進(jìn)入等待狀態(tài),直到其他線程調(diào)用該 Condition 的 signal() 或 signalAll() 方法,或者當(dāng)前線程被中斷。調(diào)用 await() 方法時(shí),當(dāng)前線程會(huì)釋放持有的 Lock,在被喚醒后,會(huì)重新獲取該 Lock。示例代碼如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AwaitExample {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    public void awaitMethod() {
        lock.lock();
        try {
            System.out.println("Thread " + Thread.currentThread().getName() + " is waiting.");
            condition.await();
            System.out.println("Thread " + Thread.currentThread().getName() + " is awakened.");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
}

3.2 signal () 方法

signal() 方法會(huì)喚醒在該 Condition 上等待的單個(gè)線程。如果有多個(gè)線程在等待,只會(huì)喚醒其中一個(gè)線程,具體喚醒哪個(gè)線程是不確定的。示例代碼如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SignalExample {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    public void signalMethod() {
        lock.lock();
        try {
            System.out.println("Thread " + Thread.currentThread().getName() + " is signaling.");
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}

3.3 signalAll () 方法

signalAll() 方法會(huì)喚醒在該 Condition 上等待的所有線程。被喚醒的線程會(huì)競(jìng)爭(zhēng)獲取 Lock,獲取到 Lock 的線程將繼續(xù)執(zhí)行。示例代碼如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SignalAllExample {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    public void signalAllMethod() {
        lock.lock();
        try {
            System.out.println("Thread " + Thread.currentThread().getName() + " is signaling all.");
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

四、Condition 接口的應(yīng)用場(chǎng)景

4.1 生產(chǎn)者 - 消費(fèi)者模式

使用 Condition 接口可以實(shí)現(xiàn)更復(fù)雜的生產(chǎn)者 - 消費(fèi)者模式。例如,當(dāng)緩沖區(qū)滿時(shí),生產(chǎn)者線程等待;當(dāng)緩沖區(qū)為空時(shí),消費(fèi)者線程等待。示例代碼如下:

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Buffer {
    private final LinkedList<Integer> buffer = new LinkedList<>();
    private static final int MAX_SIZE = 5;
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    public void produce(int item) {
        lock.lock();
        try {
            while (buffer.size() == MAX_SIZE) {
                System.out.println("Buffer is full, producer is waiting.");
                notFull.await();
            }
            buffer.add(item);
            System.out.println("Produced: " + item);
            notEmpty.signal();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    public int consume() {
        lock.lock();
        try {
            while (buffer.size() == 0) {
                System.out.println("Buffer is empty, consumer is waiting.");
                notEmpty.await();
            }
            int item = buffer.removeFirst();
            System.out.println("Consumed: " + item);
            notFull.signal();
            return item;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -1;
        } finally {
            lock.unlock();
        }
    }
}
public class ProducerConsumerWithCondition {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                buffer.produce(i);
            }
        });
        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                buffer.consume();
            }
        });
        producer.start();
        consumer.start();
    }
}

4.2 多線程任務(wù)協(xié)調(diào)

在一些多線程任務(wù)中,需要根據(jù)不同的條件來(lái)協(xié)調(diào)線程的執(zhí)行順序。例如,一個(gè)線程需要等待其他幾個(gè)線程完成特定任務(wù)后才能繼續(xù)執(zhí)行,這時(shí)可以使用 Condition 接口來(lái)實(shí)現(xiàn)。

五、Condition 接口的實(shí)現(xiàn)原理

Condition 接口的實(shí)現(xiàn)通常依賴于 AbstractQueuedSynchronizer(AQS)。每個(gè) Condition 實(shí)例都有一個(gè)與之關(guān)聯(lián)的等待隊(duì)列,當(dāng)線程調(diào)用 await() 方法時(shí),會(huì)將該線程封裝成一個(gè)節(jié)點(diǎn)加入到等待隊(duì)列中,并釋放持有的 Lock。當(dāng)其他線程調(diào)用 signal() 或 signalAll() 方法時(shí),會(huì)從等待隊(duì)列中移除相應(yīng)的節(jié)點(diǎn),并將其加入到 Lock 的同步隊(duì)列中,等待獲取 Lock。

六、使用 Condition 接口的注意事項(xiàng)

6.1 鎖的獲取和釋放

在調(diào)用 Condition 接口的方法之前,必須先獲取關(guān)聯(lián)的 Lock,并且在使用完后要確保釋放 Lock,通常使用 try - finally 塊來(lái)保證這一點(diǎn)。

6.2 中斷處理

await() 方法會(huì)拋出 InterruptedException 異常,因此需要在代碼中進(jìn)行適當(dāng)?shù)漠惓L幚?,以確保線程在被中斷時(shí)能夠正確響應(yīng)。

6.3 條件判斷

在調(diào)用 await() 方法時(shí),通常需要使用 while 循環(huán)來(lái)進(jìn)行條件判斷,而不是 if 語(yǔ)句。這是因?yàn)樵诙嗑€程環(huán)境下,線程被喚醒后可能會(huì)出現(xiàn)虛假喚醒的情況,使用 while 循環(huán)可以確保條件仍然滿足。

七、總結(jié)

Condition 接口為 Java 并發(fā)編程提供了一種強(qiáng)大而靈活的線程間等待通知機(jī)制。通過(guò)與 ReentrantLock 配合使用,可以實(shí)現(xiàn)更復(fù)雜、更精細(xì)的線程同步和協(xié)作。在實(shí)際開發(fā)中,根據(jù)具體的業(yè)務(wù)需求合理使用 Condition 接口,能夠提高程序的并發(fā)性能和可靠性。同時(shí),需要注意鎖的獲取和釋放、中斷處理以及條件判斷等問(wèn)題,以避免出現(xiàn)并發(fā)問(wèn)題。

到此這篇關(guān)于探究 Java 的 Condition 接口與等待通知機(jī)制的文章就介紹到這了,更多相關(guān)java condition 等待通知機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot--- SpringSecurity進(jìn)行注銷權(quán)限控制的配置方法

    SpringBoot--- SpringSecurity進(jìn)行注銷權(quán)限控制的配置方法

    這篇文章主要介紹了SpringBoot--- SpringSecurity進(jìn)行注銷,權(quán)限控制,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot+VUE實(shí)現(xiàn)數(shù)據(jù)表格的實(shí)戰(zhàn)

    SpringBoot+VUE實(shí)現(xiàn)數(shù)據(jù)表格的實(shí)戰(zhàn)

    本文將使用VUE+SpringBoot+MybatisPlus,以前后端分離的形式來(lái)實(shí)現(xiàn)數(shù)據(jù)表格在前端的渲染,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-08-08
  • Java雪花算法的實(shí)現(xiàn)詳解

    Java雪花算法的實(shí)現(xiàn)詳解

    雪花算法(Snowflake)是一種分布式唯一ID生成算法,用于生成全局唯一的ID,使用雪花算法生成的ID通常是一個(gè)64位的整數(shù),可以根據(jù)需要進(jìn)行轉(zhuǎn)換和展示,在Java等編程語(yǔ)言中,可以使用相應(yīng)的庫(kù)或工具來(lái)生成雪花算法的ID,本文給大家介紹了Java雪花算法的實(shí)現(xiàn)
    2023-11-11
  • SpringBoot使用redis實(shí)現(xiàn)session共享功能

    SpringBoot使用redis實(shí)現(xiàn)session共享功能

    這篇文章主要介紹了pringboot項(xiàng)目使用redis實(shí)現(xiàn)session共享,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀

    logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀

    這篇文章主要為大家介紹了logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • MybatisPlus如何自定義TypeHandler映射JSON類型為L(zhǎng)ist

    MybatisPlus如何自定義TypeHandler映射JSON類型為L(zhǎng)ist

    這篇文章主要介紹了MybatisPlus如何自定義TypeHandler映射JSON類型為L(zhǎng)ist,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java嵌套for循環(huán)優(yōu)化方案分享

    Java嵌套for循環(huán)優(yōu)化方案分享

    介紹了Java中嵌套for循環(huán)的優(yōu)化方法,包括減少循環(huán)次數(shù)、合并循環(huán)、使用更高效的數(shù)據(jù)結(jié)構(gòu)、并行處理、預(yù)處理和緩存、算法優(yōu)化、盡量減少對(duì)象創(chuàng)建以及本地變量?jī)?yōu)化,通過(guò)這些方法,可以顯著提升程序的執(zhí)行效率,文章還以動(dòng)態(tài)規(guī)劃優(yōu)化示例——最長(zhǎng)遞增子序列
    2025-03-03
  • 關(guān)于java的九個(gè)預(yù)定義Class對(duì)象

    關(guān)于java的九個(gè)預(yù)定義Class對(duì)象

    這篇文章主要介紹了關(guān)于java的九個(gè)預(yù)定義Class對(duì)象,在Java中,沒(méi)有類就無(wú)法做任何事情。然而,并不是所有的類都具有面向?qū)ο筇卣?。如Math.random,并只需要知道方法名和參數(shù),需要的朋友可以參考下
    2023-05-05
  • java中BASE64加密/解密詳解(附帶源碼)

    java中BASE64加密/解密詳解(附帶源碼)

    這篇文章主要介紹了java中BASE64加密/解密的相關(guān)資料,并詳細(xì)展示了如何在Java中使用內(nèi)置的Base64類進(jìn)行編碼和解碼,文章還涵蓋不同類型的Base64編碼及其應(yīng)用場(chǎng)景,需要的朋友可以參考下
    2025-05-05
  • Java中ArrayList與順序表的概念與使用實(shí)例

    Java中ArrayList與順序表的概念與使用實(shí)例

    順序表是指用一組地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)各個(gè)元素,使得在邏輯結(jié)構(gòu)上相鄰的數(shù)據(jù)元素存儲(chǔ)在相鄰的物理存儲(chǔ)單元中的線性表,下面這篇文章主要介紹了Java?ArrayList與順序表的相關(guān)資料,需要的朋友可以參考下
    2022-01-01

最新評(píng)論