2015-06-23 14 views
13

Während ich an meiner Java-Anwendung arbeite, habe ich einen einfachen Multithreading-Fall (einen asynchronen Ressourcenlader-Thread und einen Haupt-Thread, der darauf wartet, dass der Ladevorgang beendet wird, die Benutzeroberfläche mit dem Fortschritt zu aktualisieren), was ich durch Aufrufen vonThread.Yield() als schädlich angesehen?

lösen könnte
while(!foo.isInitialized()) { 
    Thread.yield(); 
} 

im Hauptthread. Ich bin mir bewusst, dass es robustere Lösungen gibt; immer noch, der Lader ist nicht von mir entworfen und es ist eine im Grunde nur Lese-Bibliothek (ich kann nicht einfach wait(), weil ich kann es nicht senden mir eine notify(); auch, es stirbt nicht nach der Fertigstellung), und ich muss nur warten, bis das Laden abgeschlossen ist.

Java doc sagt, dass (beachten Sie diese not present in 1,6 docs war und wurde von 1,7 docs hinzugefügt)

Es ist selten angezeigt, diese Methode zu verwenden.

NetBeans warnt mich, dass

Invocation von Verfahren yield() auf java.lang.Thread in der Regel Synchronisationsprobleme verwendet wird, um Maskerade und sollte vermieden werden.

Google Codepro AnalytiX, OTOH, sagt

Verfahren Thread.yield() sollte nicht verwendet werden, weil sein Verhalten auf allen Plattformen nicht konsistent ist.

Sollte ich mit diesen Warnungen betroffen sein und versuchen, eine bessere Lösung zu finden (alle Vorschläge sind willkommen), oder sollte ich diejenigen, die als „Warnung Lärm“ betrachten und zu unterdrücken/sie ignorieren?

Hinweis: Ich dachte über die offensichtliche Möglichkeit der Verwendung sleep() (Are Thread.sleep(0) and Thread.yield() statements equivalent? ist hier erwähnenswert); Trotzdem, wenn yield kein "Bonus" über das ständige Schlafen hat, warum stellt Java es überhaupt zur Verfügung - und was sind dann die gültigen Anwendungsfälle dafür?

leicht bezogen werden: Is there a better solution to Thread.yield()? & Thread.Sleep or Thread.Yield

+0

Sehr schädlich. Was ist, wenn es keinen anderen ready-to-run-Thread gibt, dem man nachgeben kann? Wenn du auf etwas warten willst, * warte * darauf. –

+1

@DavidSchwartz Es wird einfach vom Thread-Scheduler ignoriert. – Mordechai

+0

Ja, Sie sollten besorgt sein. Kannst du mehr erklären, was du tatsächlich erreichen willst? Was ist dein Ziel hier? – markspace

Antwort

2

Das Hauptproblem bei Thread.yield() in einer while-Schleife ohne Warte Mechanik Aufruf ist, dass es einfach einen Besetzt-Warteschleife unter Verwendung von 100% eines Ihres Kerns wird.

Wenn keine anderen Threads geplant sind, wird der ermittelte Thread wahrscheinlich sehr schnell neu terminiert, was zu einer hohen CPU-Auslastung führt.

Ansonsten, in diesem Fall kann ich nicht sehen, dass es schädlicher wäre als das. Es ist jedoch ziemlich sinnlos - wenn Sie eine busy-wait-Schleife schreiben, können Sie einfach while (!foo.isInitialized()); tun und vermeiden, den Scheduler zu stressen.

Was Sie tun sollten, wenn Sie keinen Benachrichtigungsmechanismus haben können, ist zumindest in der Schleife schlafen. Dadurch können sich Ihre CPUs ein wenig ausruhen.

typische Implementierung einer solchen Schleife:

while(!foo.isInitialized()) { 
    try { 
     Thread.sleep(20); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
     return; // or handle some other way 
    } 
} 
+0

Je nachdem, wie kritisch dieser Code ist, kann er sehr viel schädlicher sein. Wenn dieser Code keine Rolle spielt, spielt das keine große Rolle. Aber wenn dies der Fall ist, können schwerwiegende Leistungsprobleme auftreten. Angenommen, der Thread, auf den wir warten, wird in einem virtuellen Kern ausgeführt, der diesen physischen Kern gemeinsam nutzt. Und überlegen Sie, was passiert, wenn wir diese Schleife endgültig verlassen und der Zweig falsch vorhergesagt wird. Das macht grundsätzlich alles falsch. –

+0

@DavidSchwartz Mit "mehr schädlich als das" - ich war in Bezug auf regelmäßige Busy-Warteschleife. Ich verstehe Ihren Kommentar nicht vollständig. Meinst du, dass das Aufrufen von 'Thread.yield()' viel schlimmer ist als ein normales busy-wait in deinem Szenario? Wenn ja, könntest du es ein bisschen mehr erklären, würde ich gerne besser verstehen! –

+0

Es könnte schädlicher sein als eine reguläre Busy-Wait-Schleife, da der Aufruf des Schedulers mehr Auswirkungen auf die Leistung haben kann als nur eine enge Spin-Schleife (indem beispielsweise Cache-Invalidierungen auf anderen Kernen verursacht werden). Aber ich interpretierte "Ich kann nicht sehen, dass es schädlicher wäre als das", um zu bedeuten, dass Sie sich keine anderen Schäden vorgestellt haben, als die, die Sie beschrieben haben. (Es gibt keine Beweise, dass der OP versteht, welchen Schaden eine vielbeschäftigte Warteschleife erleidet.) –