web-dev-qa-db-fra.com

Que signifie ce code de jonction de fil?

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();
   }
}
151
user697911

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 .

  1. Le thread principal crée et démarre les threads t1 et t2. Les deux threads commencent à fonctionner en parallèle.
  2. Le thread principal appelle t1.join() pour attendre que le thread t1 se termine.
  3. Le thread 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.
  4. Le thread principal appelle t2.join() pour attendre que le thread t2 se termine.
  5. Le thread 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.

290
Gray

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.

66
AmitG

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().

44
Avi

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

20
xxy

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.

Toutes les actions d'un thread arrivent avant qu'un autre thread ne soit renvoyé avec succès par join () sur ce 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).

8
Ivan Golovach

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

  1. Utilisation de invokeAll sur ExecutorService
  2. Utilisation de CountDownLatch
  3. Utilisation de ForkJoinPool ou newWorkStealingPool sur Executors (depuis Java 8)

Reportez-vous aux questions SE connexes:

attendez que tous les threads terminent leur travail en Java

3
Ravindra babu

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().

3
c0der

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.

1
Arjun Patil

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
}
0
Parthasarathy S