亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Java中正確使用wait, notify和notifyAll

發布時間:2021-12-04 14:20:52 來源:億速云 閱讀:169 作者:小新 欄目:編程語言

這篇文章將為大家詳細講解有關怎么在Java中正確使用wait, notify和notifyAll,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

wait, notify 和 notifyAll,這些在多線程中被經常用到的保留關鍵字,在實際開發的時候很多時候卻并沒有被大家重視。本文對這些關鍵字的使用進行了描述。

在 Java 中可以用 wait、notify 和 notifyAll  來實現線程間的通信。。舉個例子,如果你的Java程序中有兩個線程——即生產者和消費者,那么生產者可以通知消費者,讓消費者開始消耗數據,因為隊列緩 沖區中有內容待消費(不為空)。相應的,消費者可以通知生產者可以開始生成更多的數據,因為當它消耗掉某些數據后緩沖區不再為滿。

我們可以利用wait()來讓一個線程在某些條件下暫停運行。例如,在生產者消費者模型中,生產者線程在緩沖區為滿的時候,消費者在緩沖區為空的時 候,都應該暫停運行。如果某些線程在等待某些條件觸發,那當那些條件為真時,你可以用 notify 和 notifyAll  來通知那些等待中的線程重新開始運行。不同之處在于,notify 僅僅通知一個線程,并且我們不知道哪個線程會收到通知,然而 notifyAll  會通知所有等待中的線程。換言之,如果只有一個線程在等待一個信號燈,notify和notifyAll都會通知到這個線程。但如果多個線程在等待這個信 號燈,那么notify只會通知到其中一個,而其它線程并不會收到任何通知,而notifyAll會喚醒所有等待中的線程。

如何使用Wait

盡管關于wait和notify的概念很基礎,它們也都是Object類的函數,但用它們來寫代碼卻并不簡單。如果你在面試中讓應聘者來手寫代碼, 用wait和notify解決生產者消費者問題,我幾乎可以肯定他們中的大多數都會無所適從或者犯下一些錯誤,例如在錯誤的地方使用  synchronized 關鍵詞,沒有對正確的對象使用wait,或者沒有遵循規范的代碼方法。說實話,這個問題對于不常使用它們的程序員來說確實令人感覺比較頭疼。

***個問題就是,我們怎么在代碼里使用wait()呢?因為wait()并不是Thread類下的函數,我們并不能使用 Thread.call()。事實上很多Java程序員都喜歡這么寫,因為它們習慣了使用Thread.sleep(),所以他們會試圖使用wait()   來達成相同的目的,但很快他們就會發現這并不能順利解決問題。正確的方法是對在多線程間共享的那個Object來使用wait。在生產者消費者問題中,這 個共享的Object就是那個緩沖區隊列。

第二個問題是,既然我們應該在synchronized的函數或是對象里調用wait,那哪個對象應該被synchronized呢?答案是,那個 你希望上鎖的對象就應該被synchronized,即那個在多個線程間被共享的對象。在生產者消費者問題中,應該被synchronized的就是那個 緩沖區隊列。(我覺得這里是英文原文有問題……本來那個句末就不應該是問號不然不太通……)

怎么在Java中正確使用wait, notify和notifyAll

永遠在循環(loop)里調用 wait 和 notify,不是在 If 語句

現在你知道wait應該永遠在被synchronized的背景下和那個被多線程共享的對象上調用,下一個一定要記住的問題就是,你應該永遠在 while循環,而不是if語句中調用wait。因為線程是在某些條件下等待的——在我們的例子里,即“如果緩沖區隊列是滿的話,那么生產者線程應該等 待”,你可能直覺就會寫一個if語句。但if語句存在一些微妙的小問題,導致即使條件沒被滿足,你的線程你也有可能被錯誤地喚醒。所以如果你不在線程被喚 醒后再次使用while循環檢查喚醒條件是否被滿足,你的程序就有可能會出錯——例如在緩沖區為滿的時候生產者繼續生成數據,或者緩沖區為空的時候消費者 開始小號數據。所以記住,永遠在while循環而不是if語句中使用wait!我會推薦閱讀《Effective Java》,這是關于如何正確使用wait和notify的***的參考資料。

基于以上認知,下面這個是使用wait和notify函數的規范代碼模板:

// The standard idiom for calling the wait method in Java synchronized (sharedObject) {     while (condition) { sharedObject.wait();         // (Releases lock, and reacquires on wakeup)     }     // do action based upon condition e.g. take or put into queue }

就像我之前說的一樣,在while循環里使用wait的目的,是在線程被喚醒的前后都持續檢查條件是否被滿足。如果條件并未改變,wait被調用之前notify的喚醒通知就來了,那么這個線程并不能保證被喚醒,有可能會導致死鎖問題。

Java wait(), notify(), notifyAll() 范例

下面我們提供一個使用wait和notify的范例程序。在這個程序里,我們使用了上文所述的一些代碼規范。我們有兩個線程,分別名為 PRODUCER(生產者)和CONSUMER(消費者),他們分別繼承了了Producer和Consumer類,而Producer和 Consumer都繼承了Thread類。Producer和Consumer想要實現的代碼邏輯都在run()函數內。Main線程開始了生產者和消費 者線程,并聲明了一個LinkedList作為緩沖區隊列(在Java中,LinkedList實現了隊列的接口)。生產者在***循環中持續往 LinkedList里插入隨機整數直到LinkedList滿。我們在while(queue.size ==  maxSize)循環語句中檢查這個條件。請注意到我們在做這個檢查條件之前已經在隊列對象上使用了synchronized關鍵詞,因而其它線程不能在 我們檢查條件時改變這個隊列。如果隊列滿了,那么PRODUCER線程會在CONSUMER線程消耗掉隊列里的任意一個整數,并用notify來通知 PRODUCER線程之前持續等待。在我們的例子中,wait和notify都是使用在同一個共享對象上的。

import java.util.LinkedList; import java.util.Queue; import java.util.Random; /** * Simple Java program to demonstrate How to use wait, notify and notifyAll() * method in Java by solving producer consumer problem. * * @author Javin Paul */ public class ProducerConsumerInJava { public static void main(String args[]) {   System.out.println("How to use wait and notify method in Java");   System.out.println("Solving Producer Consumper Problem");   Queue<Integer> buffer = new LinkedList<>();   int maxSize = 10;   Thread producer = new Producer(buffer, maxSize, "PRODUCER");   Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");   producer.start(); consumer.start(); } } /** * Producer Thread will keep producing values for Consumer * to consumer. It will use wait() method when Queue is full * and use notify() method to send notification to Consumer * Thread. * * @author WINDOWS 8 * */ class Producer extends Thread { private Queue<Integer> queue;   private int maxSize;   public Producer(Queue<Integer> queue, int maxSize, String name){    super(name); this.queue = queue; this.maxSize = maxSize;   }   @Override public void run()   {    while (true)     {      synchronized (queue) {       while (queue.size() == maxSize) {        try {         System.out .println("Queue is full, " + "Producer thread waiting for " + "consumer to take something from queue");         queue.wait();        } catch (Exception ex) {         ex.printStackTrace(); }        }        Random random = new Random();        int i = random.nextInt();        System.out.println("Producing value : " + i); queue.add(i); queue.notifyAll();       }      }     }    } /** * Consumer Thread will consumer values form shared queue. * It will also use wait() method to wait if queue is * empty. It will also use notify method to send * notification to producer thread after consuming values * from queue. * * @author WINDOWS 8 * */ class Consumer extends Thread {   private Queue<Integer> queue;   private int maxSize;   public Consumer(Queue<Integer> queue, int maxSize, String name){    super(name);    this.queue = queue;    this.maxSize = maxSize;   }   @Override public void run() {    while (true) {     synchronized (queue) {      while (queue.isEmpty()) {       System.out.println("Queue is empty," + "Consumer thread is waiting" + " for producer thread to put something in queue");       try {        queue.wait();       } catch (Exception ex) {        ex.printStackTrace();       }      }      System.out.println("Consuming value : " + queue.remove()); queue.notifyAll();     }    }   } }

怎么在Java中正確使用wait, notify和notifyAll

為了更好地理解這個程序,我建議你在debug模式里跑這個程序。一旦你在debug模式下啟動程序,它會停止在PRODUCER或者 CONSUMER線程上,取決于哪個線程占據了CPU。因為兩個線程都有wait()的條件,它們一定會停止,然后你就可以跑這個程序然后看發生什么了 (很有可能它就會輸出我們以上展示的內容)。你也可以使用Eclipse里的Step into和Step over按鈕來更好地理解多線程間發生的事情。

本文重點:

1. 你可以使用wait和notify函數來實現線程間通信。你可以用它們來實現多線程(>3)之間的通信。

2. 永遠在synchronized的函數或對象里使用wait、notify和notifyAll,不然Java虛擬機會生成 IllegalMonitorStateException。

3. 永遠在while循環里而不是if語句下使用wait。這樣,循環會在線程睡眠前后都檢查wait的條件,并在條件實際上并未改變的情況下處理喚醒通知。

4. 永遠在多線程間共享的對象(在生產者消費者模型里即緩沖區隊列)上使用wait。

5. 基于前文提及的理由,更傾向用 notifyAll(),而不是 notify()。

怎么在Java中正確使用wait, notify和notifyAll

這是關于Java里如何使用wait,  notify和notifyAll的所有重點啦。你應該只在你知道自己要做什么的情況下使用這些函數,不然Java里還有很多其它的用來解決同步問題的方 案。例如,如果你想使用生產者消費者模型的話,你也可以使用BlockingQueue,它會幫你處理所有的線程安全問題和流程控制。如果你想要某一個線 程等待另一個線程做出反饋再繼續運行,你也可以使用CycliBarrier或者CountDownLatch。如果你只是想保護某一個資源的話,你也可 以使用Semaphore。

關于“怎么在Java中正確使用wait, notify和notifyAll”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

锡林浩特市| 商城县| 九龙城区| 八宿县| 依兰县| 莫力| 永定县| 大渡口区| 揭东县| 四子王旗| 务川| 手机| 九江市| 鲁甸县| 滕州市| 鸡泽县| 宿迁市| 宣恩县| 安康市| 北川| 秦皇岛市| 栾川县| 陆河县| 靖远县| 湘潭市| 寻乌县| 桐乡市| 漳州市| 温泉县| 新竹县| 普安县| 泰安市| 五原县| 区。| 邵阳市| 安达市| 右玉县| 兴仁县| 霞浦县| 曲松县| 汾阳市|