Dans ce code, que signifient les deux jointures et rupture? t1.join()
provoque l'arrêt de t2
jusqu'à ce que t1
se termine?
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join();
t2.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Que signifie ce code de jonction de fil?
Pour citer la Thread.join()
method javadocs :
join()
Attend la fin de ce fil.
Il existe un thread qui exécute votre exemple de code qui est probablement le thread principal .
t1
et t2
. Les deux threads commencent à fonctionner en parallèle.t1.join()
pour attendre que le thread t1
se termine.t1
est terminé et la méthode t1.join()
revient dans le thread principal. Notez que t1
aurait peut-être déjà fini avant l'appel join()
, auquel cas l'appel join()
reviendra immédiatement.t2.join()
pour attendre que le thread t2
se termine.t2
se termine (ou il l'avait peut-être terminé avant le thread t1
) et la méthode t2.join()
revient dans le thread principal.Il est important de comprendre que les threads t1
et t2
ont été exécutés en parallèle mais que le thread principal qui les a démarrés a besoin attendre qu'ils finissent avant que cela puisse continuer. C'est un modèle commun. De plus, t1
et/ou t2
auraient pu être terminés avant le thread principal y appelle join()
. Si tel est le cas, join()
n'attendra pas, mais reviendra immédiatement.
t1.join()
signifie que t2 s'arrête jusqu'à ce que t1 se termine?
Le thread principal qui appelle t1.join()
cessera de fonctionner et attendra que le thread t1
se termine. Le thread t2
est exécuté en parallèle et n'est pas affecté par l'appel de t1
ou t1.join()
.
En termes de try/catch, la join()
jette InterruptedException
, ce qui signifie que le thread principal qui appelle join()
peut lui-même être interrompu par un autre thread.
while (true) {
Avoir les jointures dans une boucle while
est un motif étrange. Généralement, vous ferez la première jointure, puis la seconde, en manipulant la InterruptedException
correctement dans chaque cas. Pas besoin de les mettre en boucle.
Ceci est une interview préférée Java.
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join(); // 1
t2.join(); // 2 These lines (1,2) are in in public static void main
break;
}
}
t1.join()
signifie que, t1 dit quelque chose comme "je veux finir en premier". Il en est de même avec t2
. Peu importe qui a commencé le thread t1
ou t2
(dans ce cas, la méthode main
), main attendra que t1
et t2
terminent leur tâche.
Cependant, un point important à noter, t1
et t2
eux-mêmes peut s'exécuter en parallèle quelle que soit la séquence d'appel de la jointure sur t1
et t2
. C'est le thread main/daemon
qui doit attendre.
join()
signifie attendre la fin d'un thread. Ceci est une méthode de blocage. Votre thread principal (celui qui effectue la join()
) attendra sur la ligne t1.join()
jusqu'à ce que t1
termine son travail, puis fera de même pour t2.join()
.
Une image vaut mieux que mille mots.
Main thread-->----->--->-->--block##########continue--->---->
\ | |
sub thread start()\ | join() |
\ | |
---sub thread----->--->--->--finish
J'espère utile, pour plus de détails, cliquez ici
Lorsque thread tA appelle tB.join (), sa cause attend non seulement que tB meure ou que tA soit interrompu, mais crée une relation "happen-before" entre la dernière instruction de tB et la suivante, après tB.join () dans tA thread.
Cela signifie programme
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
threadB.join();
while (true)
System.out.print(sharedVar);
}
}
Toujours imprimer
>> 1111111111111111111111111 ...
Mais programme
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
// threadB.join(); COMMENT JOIN
while (true)
System.out.print(sharedVar);
}
}
Peut imprimer non seulement
>> 0000000000 ... 000000111111111111111111111111 ...
Mais
>> 00000000000000000000000000000000000000000000 ...
Toujours seulement '0'.
Parce que Java Memory Model ne nécessite pas de "transférer" la nouvelle valeur de "sharedVar" de threadB vers un thread principal sans relation heppens-before (thread start, thread join, utilisation du mot clé "synchonized", utilisation de AtomicXXX variables, etc).
De la documentation Oracle page sur les jointures
La méthode
join
permet à un thread d'attendre la fin d'un autre.
Si t1 est un objet Thread
dont le thread est en cours d'exécution,
t1.join() : causes the current thread to pause execution until t1's thread terminates.
Si t2 est un objet Thread
dont le thread est en cours d'exécution,
t2.join(); causes the current thread to pause execution until t2's thread terminates.
join
API est une API de bas niveau introduite dans les versions antérieures de Java. Beaucoup de choses ont été changées au cours d'une période donnée (en particulier avec la version 1.5 de jdk) en matière de concurrence.
Vous pouvez obtenir le même résultat avec l'API Java.util.concurrent. Certains exemples sont
ExecutorService
Executors
(depuis Java 8)Reportez-vous aux questions SE connexes:
attendez que tous les threads terminent leur travail en Java
Tout simplement:t1.join()
revient après que t1
soit terminé.
Cela ne fait rien de filer t1
, sauf attendre la fin.
Naturellement, le code suivant t1.join()
ne sera exécuté qu’après le retour de t1.join()
.
Pour moi, le comportement de Join () était toujours déroutant parce que j'essayais de me rappeler qui attendrait qui. N'essayez pas de vous en souvenir de cette façon.
En dessous, c’est le mécanisme pure wait () et notify ().
Nous savons tous que, lorsque nous appelons wait () sur n'importe quel objet (t1), l'objet appelant (principal) est envoyé en salle d'attente (état Bloqué).
Ici, le fil principal appelle join () qui est wait () sous les couvertures. Donc, le fil principal attendra d'être notifié. La notification est donnée par t1 à la fin de son exécution (achèvement du thread).
Après avoir reçu la notification, le principal sort de la salle d’attente et procède à son exécution.
J'espère que ça aide!
package join;
public class ThreadJoinApp {
Thread th = new Thread("Thread 1") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
Thread th2 = new Thread("Thread 2") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
//Thread 2 waits until the thread 1 successfully completes.
try {
th.join();
} catch( InterruptedException ex) {
System.out.println("Exception has been caught");
}
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
public static void main(String[] args) {
ThreadJoinApp threadJoinApp = new ThreadJoinApp();
threadJoinApp.th.start();
threadJoinApp.th2.start();
}
//Happy coding -- Parthasarathy S
}