Ich bin etwas verwirrt über die Verwendung der yield()
Methode in Java, insbesondere im folgenden Beispielcode. Ich habe auch gelesen, dassield () verwendet wird, um die Ausführung eines Threads zu verhindern.
Meine Fragen sind:
Ich glaube, dass der folgende Code sowohl bei Verwendung
yield()
als auch bei Nichtverwendung zu derselben Ausgabe führt . Ist das richtig?Was sind eigentlich die Hauptverwendungen von
yield()
?Inwiefern
yield()
unterscheidet es sich von denjoin()
undinterrupt()
Methoden?
Das Codebeispiel:
public class MyRunnable implements Runnable {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
for(int i=0; i<5; i++) {
System.out.println("Inside main");
}
}
public void run() {
for(int i=0; i<5; i++) {
System.out.println("Inside run");
Thread.yield();
}
}
}
Ich erhalte die gleiche Ausgabe mit dem obigen Code, sowohl mit als auch ohne yield()
:
Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run
yield()
und nicht. Wenn Sie ein großes i anstelle von 5 haben, können Sie den Effekt deryield()
Methode sehen.Antworten:
Quelle: http://www.javamex.com/tutorials/threads/yield.shtml
quelle
Ich sehe, dass die Frage mit einem Kopfgeld reaktiviert wurde und nun gefragt wird, wozu die praktischen Verwendungszwecke
yield
dienen. Ich werde ein Beispiel aus meiner Erfahrung geben.Wie wir wissen,
yield
wird der aufrufende Thread gezwungen, den Prozessor aufzugeben, auf dem er ausgeführt wird, damit die Ausführung eines anderen Threads geplant werden kann. Dies ist nützlich, wenn der aktuelle Thread seine Arbeit vorerst beendet hat, aber schnell zum Anfang der Warteschlange zurückkehren und prüfen möchte, ob sich eine Bedingung geändert hat. Wie unterscheidet sich das von einer Bedingungsvariablen?yield
ermöglicht es dem Thread, viel schneller in einen laufenden Zustand zurückzukehren. Beim Warten auf eine Bedingungsvariable wird der Thread angehalten und muss warten, bis ein anderer Thread signalisiert, dass er fortgesetzt werden soll.yield
Im Grunde heißt es: "Erlaube, dass ein anderer Thread ausgeführt wird, aber erlaube mir, sehr bald wieder an die Arbeit zu gehen, da ich erwarte, dass sich in meinem Zustand sehr schnell etwas ändert." Dies deutet auf ein starkes Spinnen hin, bei dem sich ein Zustand schnell ändern kann, das Anhalten des Threads jedoch zu einem großen Leistungseinbruch führen würde.Aber genug Geplapper, hier ist ein konkretes Beispiel: das Wellenfront-Parallelmuster. Ein grundlegendes Beispiel für dieses Problem ist die Berechnung der einzelnen "Inseln" von 1s in einem zweidimensionalen Array, das mit 0s und 1s gefüllt ist. Eine "Insel" ist eine Gruppe von Zellen, die entweder vertikal oder horizontal nebeneinander liegen:
Hier haben wir zwei Inseln von 1s: oben links und unten rechts.
Eine einfache Lösung besteht darin, einen ersten Durchgang über das gesamte Array durchzuführen und die 1-Werte durch einen inkrementierenden Zähler zu ersetzen, sodass am Ende jede 1 durch ihre Sequenznummer in der Hauptreihenfolge ersetzt wurde:
Im nächsten Schritt wird jeder Wert durch das Minimum zwischen sich und den Werten seiner Nachbarn ersetzt:
Wir können jetzt leicht feststellen, dass wir zwei Inseln haben.
Der Teil, den wir parallel ausführen möchten, ist der Schritt, in dem wir die Mindestwerte berechnen. Ohne zu sehr ins Detail zu gehen, erhält jeder Thread verschachtelte Zeilen und stützt sich auf die Werte, die von dem Thread berechnet wurden, der die obige Zeile verarbeitet. Daher muss jeder Thread etwas hinter dem Thread zurückbleiben, der die vorherige Zeile verarbeitet, muss aber auch innerhalb einer angemessenen Zeit mithalten. Weitere Details und eine Implementierung werden von mir in diesem Dokument vorgestellt . Beachten Sie, dass die Verwendung
sleep(0)
mehr oder weniger dem C-Äquivalent von entsprichtyield
.In diesem Fall
yield
wurde verwendet, um jeden Thread nacheinander zum Anhalten zu zwingen. Da jedoch der Thread, der die benachbarte Zeile verarbeitet, in der Zwischenzeit sehr schnell vorrücken würde, würde sich eine Bedingungsvariable als katastrophale Wahl erweisen.Wie Sie sehen können,
yield
handelt es sich um eine ziemlich feinkörnige Optimierung. Wenn Sie es an der falschen Stelle verwenden, z. B. wenn Sie auf einen Zustand warten, der sich selten ändert, wird die CPU übermäßig ausgelastet.Entschuldigung für das lange Geschwätz, hoffe ich habe mich klar ausgedrückt.
quelle
yield
wenn die Bedingung nicht erfüllt ist, um den anderen Threads die Möglichkeit zu geben, mit der Berechnung fortzufahren, anstatt mehr zu verwenden. Level-Synchronisationsprimitive, richtig?yield
.Über die Unterschiede zwischen
yield()
,interrupt()
undjoin()
- in der Regel nicht nur in Java:Speziell für Java siehe
Beitritt:
Wie benutze ich Thread.join? (hier auf StackOverflow)
Wann kann man Threads verbinden?
Nachgeben:
Unterbrechen:
Ist Thread.interrupt () böse? (hier auf StackOverflow)
quelle
wait()
nicht um eine Verknüpfung, sondern um eine Sperre für das Objekt, das der aufrufende Thread zu erfassen versucht. Er wartet, bis die Sperre von anderen freigegeben und vom Thread erfasst wurde. Meine Antwort wurde entsprechend angepasst.Erstens ist die eigentliche Beschreibung
Nun ist es sehr wahrscheinlich, dass Ihr Hauptthread die Schleife fünfmal ausführt, bevor die
run
Methode des neuen Threads ausgeführt wird, sodass alle Aufrufe erst ausgeführtyield
werden, nachdem die Schleife im Hauptthread ausgeführt wurde.join
stoppt den aktuellen Thread, bis diejoin()
Ausführung des Threads, mit dem aufgerufen wird, abgeschlossen ist.interrupt
unterbricht den Thread, für den es aufgerufen wird, und verursacht eine InterruptedException .yield
Ermöglicht einen Kontextwechsel zu anderen Threads, sodass dieser Thread nicht die gesamte CPU-Auslastung des Prozesses beansprucht.quelle
SwitchToThread()
Anruf ist besser als Sleep (0) , und dies soll ein Fehler in Java sein :)Es gibt keinen praktischen Unterschied
Thread.yield()
zwischen Java-Versionen seit 6 bis 9.TL; DR;
Schlussfolgerungen basierend auf OpenJDK-Quellcode ( http://hg.openjdk.java.net/ ).
Wenn die HotSpot-Unterstützung von USDT-Sonden (Informationen zur Systemverfolgung werden im dtrace-Handbuch beschrieben ) und der JVM-Eigenschaft nicht berücksichtigt wird, ist der
ConvertYieldToSleep
Quellcode vonyield()
nahezu identisch. Siehe Erklärung unten.Java 9 :
Thread.yield()
ruft die betriebssystemspezifische Methode aufos::naked_yield()
:Unter Linux:
Unter Windows:
Java 8 und früher:
Thread.yield()
ruft die betriebssystemspezifische Methode aufos::yield()
:Unter Linux:
Unter Windows:
Wie Sie sehen können, ist
Thread.yeald()
Linux unter Linux für alle Java-Versionen identisch.Sehen wir uns Windows
os::NakedYield()
von JDK 8 an:Der Unterschied zwischen Java 9 und Java 8 bei der zusätzlichen Überprüfung der Existenz der Win32-API-
SwitchToThread()
Methode. Für Java 6 ist derselbe Code vorhanden. DerQuellcode von
os::NakedYield()
in JDK 7 unterscheidet sich geringfügig, weist jedoch dasselbe Verhalten auf:Die zusätzliche Prüfung wurde aufgrund der
SwitchToThread()
Methode gelöscht, die seit Windows XP und Windows Server 2003 verfügbar ist (siehe msdn-Hinweise ).quelle
Yield schlägt der CPU vor, den aktuellen Thread anzuhalten und Threads mit höherer Priorität auszuführen. Mit anderen Worten: Zuweisen eines Werts mit niedriger Priorität zum aktuellen Thread, um Platz für kritischere Threads zu lassen.
NEIN, die beiden führen zu unterschiedlichen Ergebnissen. Ohne ein Yield () führt der Thread, sobald er die Kontrolle erhält, die 'Inside Run'-Schleife auf einmal aus. Bei einem Yield () druckt der Thread jedoch, sobald er die Kontrolle erhält, den 'Inside Run' einmal und übergibt ihn dann gegebenenfalls an einen anderen Thread. Wenn kein Thread ansteht, wird dieser Thread erneut fortgesetzt. Jedes Mal, wenn "Inside Run" ausgeführt wird, wird nach anderen Threads gesucht, die ausgeführt werden sollen. Wenn kein Thread verfügbar ist, wird der aktuelle Thread weiterhin ausgeführt.
Yield () dient dazu, anderen wichtigen Threads Platz zu geben, join () wartet darauf, dass ein anderer Thread seine Ausführung abschließt, und Interrupt () dient dazu, einen aktuell ausgeführten Thread zu unterbrechen, um etwas anderes zu tun.
quelle
Without a yield(), once the thread gets control it will execute the 'Inside run' loop in one go
? Bitte klären Sie.Thread.yield()
Bewirkt, dass der Thread vom Status "Laufen" in den Status "Ausführbar" wechselt. Hinweis: Der Thread wird nicht in den Status "Warten" versetzt.quelle
RUNNING
Status fürjava.lang.Thread
Instanzen. Dies schließt jedoch einen nativen "laufenden" Status für den nativen Thread nicht aus, für den eineThread
Instanz ein Proxy ist.Thread.yield ()
beitreten()
quelle
Ausbeute () wird hauptsächlich verwendet, um eine Multithreading-Anwendung anzuhalten.
Alle diese Methodenunterschiede sind :ield () hält den Thread an, während ein anderer Thread ausgeführt wird, und kehrt nach Abschluss dieses Threads zurück. join () bringt den Anfang der Threads zusammen, die bis zum Ende ausgeführt werden, und eines anderen Threads, der ausgeführt wird, nachdem dieser Thread ausgeführt wurde beendet, Interrupt () stoppt die Ausführung eines Threads für eine Weile.
quelle
yield
es verwendet werden sollte.