簡體   English   中英

Java線程循環Notify()和Wait()

[英]Java Threading Cyclic Notify() and Wait()

我在Java中有一個代碼,其中兩個對象等待並在一個處理完成時互相通知。 在下面的示例中,並假設沒有語法錯誤,我將簡化代碼(我只是想讓您知道此處的邏輯比語法更重要)。

假設我有對象A,它是具有此偽代碼的線程

class A is Thread {
    run() {
        while(true) {
            wait(); // wait for signal from B
            // then do something if signal received
            B.signal(); // let B know that we're done and wait again 
        }
    }
}

然后我們在這里B也是一個具有此偽代碼的線程

class B is Thread {
    run() {
        while(true) {
            // Do something
            A.signal(); // Let A know to continue processing
            wait(); // Wait for signal from A before doing something again
        }
    }
}

如您所見,這是一個周期。 問題是我遇到了死鎖,這是因為當A完成處理后,它會在等待之前通知B進行工作。但是到通知B時,仍有可能A尚未到達代碼中的wait()和B已經在調用A.signal()並導致死鎖。

如何正確解決此問題? 我想到的解決方案是,當通知B工作時,我將讓B的線程休眠數毫秒,但我認為這不是一個好主意。 任何幫助表示贊賞,在此先感謝。

當您使用notify()時,這應與狀態更改關聯。

使用wait()時,應將其與狀態更改檢查相關聯。

在實際代碼中,您僅應在等待某些內容時等待。

注意:wait()可能會虛假喚醒,這並不意味着調用notify()。 如您所見,如果什么都沒有等待,則notify()不會執行任何操作。


您可以使用BlockingQueue在線程之間傳遞工作/消息,而不是使用此模式。 這具有等待/通知和內置工作的對象。

但是,由於通常需要一個線程來完成工作,因此內置了ExecutorService。 這使您可以將工作傳遞給線程池並收集結果。

簡而言之,您應該使用ExecutorService。

如果A使用B的結果,那么您可以考慮使用BlockingQueue

Javadoc所述 ,您需要將wait調用放入檢查條件的循環中。 否則,如果沒有可檢查的條件變量或表達式,則可能由於未在此等待而錯過了通知。

另外,正如其他人指出的那樣,您需要保留正在調用waitnotify方法的對象的監視器; 這就是synchronized關鍵字的作用。

在下面的修復中,條件非常簡單; 這是一個在類A和B中稱為notified的變量。

另外,為正確起見,A和B需要彼此了解。 在您的代碼中,您似乎正在調用靜態方法。 但是notify方法需要在實例上調用,因此您需要在B和A中分別保留對A和B實例的引用。

這樣可以解決問題:

class A is Thread {
    private B b;
    private boolean notified;

    public void run() {
        while(true) {
            synchronized(this) {
                while (!notified) {
                    try {
                        wait(); // wait for signal from B
                    } catch (InterruptedException e) {}
                }
                notified = false;
            }
            synchronized(b) {
                // then do something if signal received
                b.notified = true;
                b.notify(); // let B know that we're done and wait again 
            }
        }
    }
}

class B is Thread {
    private A a;
    private boolean notified;
    public void run() {
        while(true) {
            synchronized(a) {
                // Do something
                a.notified = true;
                a.notify(); // Let A know to continue processing
            }
            synchronized(this) {
                while (!notified) {
                    try {
                        wait(); // Wait for signal from A before doing something again
                    } catch (InterruptedException e) {}
                }
                notified = false;
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM