JavaNotify:實現線程間通信的利器

Java是目前最流行的編程語言之一,其並發編程能力也是相當強大的。在多線程編程中,線程間的通信無疑是非常關鍵的。Java提供了多種方式來實現線程間通信,其中最常見的方式之一就是使用對象的wait()和notify()方法。這種方式不僅簡單易用,而且在Java中廣泛應用於各種場景下。

一、wait-notify機制的概述

wait-notify機制是Java中實現線程間通信的一種機制。它通過在不同的線程之間共享對象來實現線程間的通信。具體來說,某個線程調用對象的wait()方法後,會讓該線程處於等待狀態,並且該線程釋放所持有的對象鎖;而另一個線程調用該對象的notify()方法後,會使得等待中的線程被喚醒並且重新競爭對象鎖。因此,wait-notify機制可以幫助我們更好地控制線程的執行。

二、wait-notify機制的使用

1. wait()方法

java.lang.Object提供了wait()方法,用於將當前的線程置入“睡眠”狀態,且只有等待另一個線程來喚醒此線程。wait()方法常用於線程間交互/通信的場合,通常有線程A調用了對象的wait()方法進入等待狀態,而線程B調用了相同對象的notify()或notifyAll()方法,使得該對象的等待線程重新進入可運行狀態。


/**
 * wait方法
 */
public class WaitDemo implements Runnable{
    private static Object object = new Object();
    @Override
    public void run() {
        synchronized (object){
            try {
                System.out.println(Thread.currentThread().getName() + " wait開始..");
                object.wait();
                System.out.println(Thread.currentThread().getName() + " 被喚醒..");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        WaitDemo waitDemo1 = new WaitDemo();
        WaitDemo waitDemo2 = new WaitDemo();
        Thread thread1 = new Thread(waitDemo1, "線程1");
        Thread thread2 = new Thread(waitDemo2, "線程2");
        thread1.start();
        thread2.start();
        System.out.println("主線程睡眠2秒開始..");
        Thread.sleep(2000); //主線程睡眠3秒
        System.out.println("主線程睡眠2秒結束..");
        synchronized (object){
            object.notifyAll();
        }
        System.out.println("主線程喚醒等待線程結束..");
    }
}

注意事項:

  • wait方法必須使用在synchronized同步中。
  • wait方法會釋放鎖,而notity方法不會釋放鎖。
  • wait方法和notify,notifyAll方法不會自動釋放鎖。

2. notify()方法

java.lang.Object提供了notify()方法,喚醒一個因調用了wait()方法而處於阻塞狀態的線程。


/**
 * notify方法
 */
public class NotifyDemo implements Runnable{
    private static Object object = new Object();
    @Override
    public void run() {
        synchronized (object){
            System.out.println(Thread.currentThread().getName() + " 進入等待狀態..");
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 被喚醒..");
        }
    }

    public static void main(String[] args) {
        NotifyDemo notifyDemo = new NotifyDemo();
        Thread thread1 = new Thread(notifyDemo, "線程1");
        Thread thread2 = new Thread(notifyDemo, "線程2");
        thread1.start();
        thread2.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (object){
            object.notify(); //隨機喚醒一個線程
            //object.notifyAll(); 喚醒所有線程
        }
        System.out.println("主線程喚醒所有線程結束..");
    }
}

三、wait-notify機制的注意事項

1. Wait和Notify的阻塞隊列

線程在爭取到鎖之後,如果發現自己無法繼續執行,就會釋放鎖,並進入該鎖對象的等待隊列(wait-set)中。在鎖被釋放的同時,該線程也進入到該鎖的等待隊列中,並且會掛起線程。當鎖被另一個線程重新競爭並成功獲取後,它就會喚醒該鎖等待隊列中的某個線程,喚醒的操作由notify或者notifyAll方法完成。

2. 避免因過多的notify()而導致の虛假喚醒(Spurious Wakeup)問題

由於操作系統底層的原因,某些情況下JVM會在沒有notify()調用的情況下自動喚醒waiting線程。例如:CPU資源不足,只要有線程有等待狀態結束了,它就會進行喚醒操作。

為了避免這種情況的發生,往往需要將在wait()的時候用while來判斷條件,以保證線程在喚醒後,會重新判斷條件並決定是否執行後續的工作。以下是一個示例代碼:


/**
 * 避免虛假喚醒問題
 */
public class WaitNotifyDemo implements Runnable{
    private static final Object object = new Object();
    private static boolean flag;

    @Override
    public void run() {
        synchronized (object){
            while (!flag){
                try {
                    System.out.println(Thread.currentThread().getName() + "等待中..");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "被喚醒..");
        }
    }

    public static void main(String[] args) {
        WaitNotifyDemo waitNotifyDemo = new WaitNotifyDemo();
        Thread thread1 = new Thread(waitNotifyDemo, "線程1");
        Thread thread2 = new Thread(waitNotifyDemo, "線程2");
        thread1.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (object){
            flag = true;
            System.out.println("flag = true,喚醒所有線程..");
            object.notifyAll();
        }
    }
}

總結

本文介紹了Java中實現線程間通信的利器——wait-notify機制。wait-notify機制通過在不同的線程之間共享對象來實現線程間的通信,使用起來簡單易懂,適用於各種場景。然而在使用過程中,需注意wait-notify機制的細節和注意事項。我們通過編寫示例代碼,希望能幫助讀者更好地理解wait-notify機制。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/295990.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-27 12:57
下一篇 2024-12-27 12:57

相關推薦

  • Python刷課:優化學習體驗的利器

    Python刷課作為一種利用自動化技術優化學習體驗的工具已經被廣泛應用。它可以幫助用戶自動登錄、自動答題等,讓用戶在學習過程中可以更加專註於知識本身,提高效率,增加學習樂趣。 一、…

    編程 2025-04-29
  • lsw2u1:全能編程開發工程師的利器

    lsw2u1是一款多功能工具,可以為全能編程開發工程師提供便利的支持。本文將從多個方面對lsw2u1做詳細闡述,並給出對應代碼示例。 一、快速存取代碼段 在日常開發中,我們總會使用…

    編程 2025-04-29
  • Python線程等待指南

    本文將從多個方面詳細講解Python線程等待的相關知識。 一、等待線程結束 在多線程編程中,經常需要等待線程執行完畢再進行下一步操作。可以使用join()方法實現等待線程執行完畢再…

    編程 2025-04-29
  • Python兩個線程交替打印1到100

    這篇文章的主題是關於Python多線程的應用。我們將會通過實際的代碼,學習如何使用Python兩個線程交替打印1到100。 一、創建線程 在Python中,我們可以使用Thread…

    編程 2025-04-28
  • ROS線程發布消息異常解決方法

    針對ROS線程發布消息異常問題,我們可以從以下幾個方面進行分析和解決。 一、檢查ROS代碼是否正確 首先,我們需要檢查ROS代碼是否正確。可能會出現的問題包括: 是否正確初始化RO…

    編程 2025-04-28
  • HBuilder2.0:一站式開發利器

    本文將從如下幾個方面對HBuilder2.0進行詳細闡述,幫助初學者快速了解並開始使用該工具: 一、簡介 HBuilder2.0是一個跨平台的HTML5集成開發工具。它綜合了編碼、…

    編程 2025-04-28
  • Powersploit:安全評估與滲透測試的利器

    本文將重點介紹Powersploit,並給出相關的完整的代碼示例,幫助安全人員更好地運用Powersploit進行安全評估和滲透測試。 一、Powersploit簡介 Powers…

    編程 2025-04-28
  • JL Transaction – 實現分布式事務管理的利器

    本文將為大家介紹JL Transaction,這是一款可以實現分布式事務管理的開源事務框架,它可以幫助企業在分布式環境下有效地解決事務的一致性問題,從而保障系統的穩定性和可靠性。 …

    編程 2025-04-28
  • 全自動股票交易軟件:實現自動交易賺取更多收益的利器

    全自動股票交易軟件是一款能夠幫助股票投資者實現自動交易,據此獲取更多收益的利器。本文將從多個方面詳細闡述該軟件的特點、優點、使用方法及相關注意事項,以期幫助讀者更好地了解和使用該軟…

    編程 2025-04-27
  • Python線程池並發爬蟲

    Python線程池並發爬蟲是實現多線程爬取數據的常用技術之一,可以在一定程度上提高爬取效率和數據處理能力。本文將從多個方面對Python線程池並發爬蟲做詳細的闡述,包括線程池的實現…

    編程 2025-04-27

發表回復

登錄後才能評論