2012-04-12 60 views
2

我很困惑Java的notify()。以下示例來自教科書。Java線程通知()與notifyAll()

public synchronized consume() { 
    while(queue.isEmpty()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    // Assume that getElement() notifies to producers. 
    element = queue.getElement(); 
    ... 
} 

public synchronized produce() { 
    while(queue.isFull()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    element = new Element(); 
    ... 
    queue.addElement(element); 
    notifyAll(); 
} 

我很理解上面例子中的方法produce()。然而,誰能告訴我爲什麼我們在第一種方法(consume())結束時不使用notifyAll()?簡而言之,爲什麼不這樣:

public synchronized consume() { 
    while(queue.isEmpty()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    // Assume that getElement() notifies to producers. 
    element = queue.getElement(); 
    ... 
    notifyAll(); 
} 

非常感謝!

此致敬禮。

回答

6

我同意你的@Slash。在您的代碼示例中,由於您要從隊列中移除元素,因此有人需要通知正在等待isEmpty()循環的生產者。然而,你的代碼說:

// Assume that getElement() notifies to producers. 
element = queue.getElement(); 

這樣評論意味着在某種程度上getElement()電話notify()notifyAll()

對於短,爲什麼不喜歡這樣的:

是的,你的代碼會工作,雖然你需要刪除的評論。 :-)

通常在這些生產者/消費者模式中,有兩個鎖:一個是隊列爲空時,另一個爲已滿。然後消費者可以在隊列不再滿時告知生產者,並且喚醒其他消費者。在這種情況下,你也可以使用單一的notify(),因爲你只需要喚醒單個消費者或單個生產者。此處使用notifyAll()是因爲只有一個對象是​​。

此外,對於後人,這是非常重要你注意到while()環路if語句。即使在使用notify()和兩個鎖時,多個生產者/消費者模型中的競爭條件也必須受到保護。虛假喚醒也是一個問題。更多關於這裏:

http://256stuff.com/gray/docs/misc/producer_consumer_race_conditions/

+0

非常感謝,格雷。 :-) – 2012-04-12 02:47:04

1

在這種情況下,通知在生產時使用,告訴消費者現在有東西需要消費,以便其中一個可以喚醒並消費。假設當消費者剛剛消耗掉的東西

通知內getElement()發生:

// Assume that getElement() notifies to producers. 
+0

@dlev正確,請編輯。 – EJP 2012-04-12 00:40:55

+0

謝謝,夥計。 :-) – 2012-04-12 02:47:55