Sie müssen das Objekt notify
, die auf wait
ed sein wird nicht der Thread, der wartet.
In Ihrem Fall ist das Objekt wait
ed on eine Instanz einer anonymen inneren Klasse, was problematisch ist, weil Sie nicht einfach einen Verweis darauf erhalten können, um notify
it. Sie könnten dies lösen, indem Thread
direkt erstreckt:
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println("thread1 is started, waiting for notify()");
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
System.out.println(e.getLocalizedMessage());
}
}
System.out.println("waiting is over");
}
};
Nun ist die this
(in synchronized (this)
) auf das Gewinde selbst bezieht, und die wait
auch auf dem Thread-Objekt aufgerufen wird. In diesem Fall sollte Ihr aktueller Anruf an notify
in Ordnung sein, da es das gleiche Objekt benachrichtigt (was passiert in diesem Fall ist der Thread, der wartet - aber um klar zu sein, muss das nicht der Fall sein).
Es ist nicht empfehlenswert, ein Objekt für die Synchronisation zu verwenden, das auch anderweitig verwendet werden kann; Instanzen Thema wären ein Beispiel dafür, und in der Tat die documentation rät ausdrücklich dagegen:
Es wird empfohlen, Anwendungen wait
, nicht notify
oder notifyAll
auf Thread
Instanzen verwenden.
Auch sollten Sie richtig handhaben Spurious Wakeup; das heißt, wait
kann zurückgeben, weil notify
/notifyAll
an anderer Stelle aufgerufen wurde oder vielleicht gar nicht aufgerufen wurde. Wie die Dokumentation also says:
Ein Thread kann auch aufwachen, ohne benachrichtigt, unterbrochen oder Zeitüberschreitung, ein so genanntes Spurious Wakeup. Während dies in der Praxis selten vorkommt, müssen Anwendungen dagegen vorgehen, indem sie nach der Bedingung suchen, die den Thread geweckt haben sollte, und weiter warten, wenn die Bedingung nicht erfüllt ist. Mit anderen Worten, wartet immer in Schleifen [...]
Daher Ihr Beispiel wirklich eine separate Variable verwenden sollte zu verfolgen, ob die Wakeup beabsichtigt war (aufgrund einer expliziten notify
) oder nicht auftreten sollte.
Sie müssen 'wait()' und 'notify()' auf demselben Objekt aufrufen. Sie tun das nicht in Ihrem Code - Sie rufen implizit 'wait()' auf dem 'Runnable'-Objekt und' notify() 'auf dem' Thread'-Objekt auf. – Jesper
'wait()' und 'notify()' sind Low-Level-Methoden, die auf sehr spezifische Weise zur Implementierung von Synchronisationsklassen auf höherer Ebene verwendet werden. https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html Sie werden wahrscheinlich in Schwierigkeiten geraten, wenn Sie sie anders verwenden. In den meisten Fällen können Sie auch die Synchronisierungsklassen auf höherer Ebene verwenden, die vom 'java.util.concurrent'-Paket bereitgestellt werden, und die mit der Erstellung Ihrer eigenen verbundenen Risiken vermeiden. –
Bezogen auf http://Stackoverflow.com/questions/17840397/concept-behind-putting-wait-notify-methods-in-object-class/17841450#17841450 – Gray