Je suis un peu confus quant à l'utilisation de la yield()
méthode en Java, en particulier dans l'exemple de code ci-dessous. J'ai également lu que yield () est «utilisé pour empêcher l'exécution d'un thread».
Mes questions sont:
Je crois que le code ci-dessous donne le même résultat lors de son utilisation
yield()
et de son non-utilisation. Est-ce correct?Quelles sont, en fait, les principales utilisations de
yield()
?En quoi
yield()
diffère-t-join()
il desinterrupt()
méthodes et ?
L'exemple de code:
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();
}
}
}
J'obtiens le même résultat en utilisant le code ci-dessus avec et sans utiliser yield()
:
Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run
yield()
et non. lorsque vous avez un grand i plutôt que 5, vous pouvez voir l'effet de layield()
méthode.Réponses:
Source: http://www.javamex.com/tutorials/threads/yield.shtml
la source
Je vois que la question a été réactivée avec une prime, demandant maintenant quelles en sont les utilisations pratiques
yield
. Je vais donner un exemple de mon expérience.Comme nous le savons,
yield
force le thread appelant à abandonner le processeur sur lequel il s'exécute afin qu'un autre thread puisse être programmé pour s'exécuter. Ceci est utile lorsque le thread en cours a terminé son travail pour le moment mais veut revenir rapidement au début de la file d'attente et vérifier si une condition a changé. En quoi est-ce différent d'une variable de condition? dit essentiellement "autoriser un thread différent à fonctionner, mais permettez-moi de me remettre au travail très rapidement car je m'attends à ce que quelque chose change très très rapidement dans mon état". Cela fait allusion à une rotation occupée, où une condition peut changer rapidement mais la suspension du thread entraînerait une perte de performances importante.yield
permet au thread de revenir beaucoup plus rapidement à un état d'exécution. Lors de l'attente d'une variable de condition, le thread est suspendu et doit attendre qu'un autre thread signale qu'il doit continuer.yield
Mais assez de babillage, voici un exemple concret: le motif parallèle du front d'onde. Un exemple de base de ce problème est le calcul des «îlots» individuels de 1 dans un tableau bidimensionnel rempli de 0 et de 1. Un «îlot» est un groupe de cellules adjacentes les unes aux autres verticalement ou horizontalement:
Ici, nous avons deux îles de 1: en haut à gauche et en bas à droite.
Une solution simple consiste à effectuer un premier passage sur l'ensemble du tableau et à remplacer les valeurs 1 par un compteur incrémentiel de sorte qu'à la fin, chaque 1 soit remplacé par son numéro de séquence dans l'ordre principal de la ligne:
Dans l'étape suivante, chaque valeur est remplacée par le minimum entre elle-même et les valeurs de ses voisins:
Nous pouvons maintenant facilement déterminer que nous avons deux îles.
La partie que nous voulons exécuter en parallèle est l'étape où nous calculons les minimums. Sans entrer trop dans les détails, chaque thread obtient des lignes de manière entrelacée et s'appuie sur les valeurs calculées par le thread traitant la ligne ci-dessus. Ainsi, chaque thread doit être légèrement en retard par rapport au thread traitant la ligne précédente, mais doit également suivre le rythme dans un délai raisonnable. Plus de détails et une mise en œuvre sont présentés par moi-même dans ce document . Notez que l'utilisation de
sleep(0)
qui est plus ou moins l'équivalent C deyield
.Dans ce cas,
yield
on a utilisé pour forcer chaque thread à se mettre en pause, mais comme le thread traitant la ligne adjacente avançait très rapidement entre-temps, une variable de condition s'avérerait un choix désastreux.Comme vous pouvez le voir,
yield
c'est une optimisation assez fine. L'utiliser au mauvais endroit, par exemple attendre une condition qui change rarement, entraînera une utilisation excessive du processeur.Désolé pour le long babillage, j'espère que je me suis fait comprendre.
la source
yield
lorsque la condition n'est pas satisfaite pour donner aux autres threads la chance de procéder au calcul, plutôt que d'utiliser plus haut- primitives de synchronisation de niveau, non?yield
.Au sujet des différences entre
yield()
,interrupt()
etjoin()
- en général, pas seulement en Java:Pour Java en particulier, voir
Joindre:
Comment utiliser Thread.join? (ici sur StackOverflow)
Quand rejoindre les discussions?
Rendement:
Interrompre:
Thread.interrupt () est-il maléfique? (ici sur StackOverflow)
la source
wait()
n'est pas une jointure, il s'agit d'un verrou sur l'objet que le thread appelant tente d'acquérir - il attend que le verrou soit libéré par d'autres et acquis par le thread. J'ai modifié ma réponse en conséquence.Premièrement, la description réelle est
Maintenant, il est très probable que votre thread principal exécutera la boucle cinq fois avant que la
run
méthode du nouveau thread ne soit exécutée, donc tous les appels àyield
ne se produiront qu'après l'exécution de la boucle du thread principal.join
arrêtera le thread en cours jusqu'à ce que le thread appelé avecjoin()
ait fini de s'exécuter.interrupt
va interrompre le thread sur lequel il est appelé, provoquant InterruptedException .yield
permet un basculement de contexte vers d'autres threads, de sorte que ce thread ne consommera pas toute l'utilisation du processeur du processus.la source
SwitchToThread()
appel est meilleur que Sleep (0) et cela devrait être un bogue en Java :)Il n'y a pas de différence pratique
Thread.yield()
entre les versions de Java depuis 6 à 9.TL, DR;
Conclusions basées sur le code source d'OpenJDK ( http://hg.openjdk.java.net/ ).
Si vous ne prenez pas en compte le support HotSpot des sondes USDT (les informations de traçage du système sont décrites dans le guide dtrace ) et la propriété JVM,
ConvertYieldToSleep
le code source deyield()
est presque le même. Voir l'explication ci-dessous.Java 9 :
Thread.yield()
appelle la méthode spécifique au système d'exploitationos::naked_yield()
:Sous Linux:
Sous Windows:
Java 8 et versions antérieures:
Thread.yield()
appelle la méthode spécifique au système d'exploitationos::yield()
:Sous Linux:
Sous Windows:
Comme vous pouvez le voir,
Thread.yeald()
sous Linux est identique pour toutes les versions de Java.Voyons Windows à
os::NakedYield()
partir du JDK 8:La différence entre Java 9 et Java 8 dans le contrôle supplémentaire de l'existence de la
SwitchToThread()
méthode de l'API Win32 . Le même code est présent pour Java 6.Le code source de
os::NakedYield()
JDK 7 est légèrement différent mais il a le même comportement:La vérification supplémentaire a été abandonnée car la
SwitchToThread()
méthode est disponible depuis Windows XP et Windows Server 2003 (voir les notes msdn ).la source
Yield suggère au CPU que vous pouvez arrêter le thread actuel et commencer à exécuter des threads avec une priorité plus élevée. En d'autres termes, attribuer une valeur de priorité faible au thread actuel pour laisser de la place pour des threads plus critiques.
NON, les deux produiront des résultats différents. Sans yield (), une fois que le thread obtient le contrôle, il exécutera la boucle 'Inside run' en une seule fois. Cependant, avec un yield (), une fois que le thread obtient le contrôle, il imprimera une fois le 'Inside run', puis passera le contrôle à un autre thread le cas échéant. Si aucun thread n'est en attente, ce thread sera repris. Ainsi, chaque fois que "Inside run" est exécuté, il recherchera d'autres threads à exécuter et si aucun thread n'est disponible, le thread actuel continuera à s'exécuter.
yield () est pour donner de la place à d'autres threads importants, join () est pour attendre qu'un autre thread termine son exécution, et interrupt () est pour interrompre un thread en cours d'exécution pour faire autre chose.
la source
Without a yield(), once the thread gets control it will execute the 'Inside run' loop in one go
? Précisez s'il vous plaît.Thread.yield()
fait passer le thread de l'état "Running" à l'état "Runnable". Remarque: cela ne fait pas passer le thread à l'état "En attente".la source
RUNNING
état pour lesjava.lang.Thread
instances. Mais cela n'empêche pas un état "d'exécution" natif pour le thread natif pour lequel uneThread
instance est un proxy.Rendement de filetage ()
joindre()
la source
La fonction principale de yield () est de mettre une application multi-thread en attente.
toutes ces différences de méthodes sont yield () met le thread en attente lors de l'exécution d'un autre thread et revenant après la fin de ce thread, join () réunira le début des threads s'exécutant jusqu'à la fin et d'un autre thread à exécuter après que ce thread ait terminé, interromp () arrêtera l'exécution d'un thread pendant un certain temps.
la source
yield
devraient être utilisés.