Concept Java Multithreading et méthode join ()

Je suis confus dans la méthode join() utilisée dans Threads en Java. Dans le code suivant:

 // Using join() to wait for threads to finish. class NewThread implements Runnable { Ssortingng name; // name of thread Thread t; NewThread(Ssortingng threadname) { name = threadname; t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread } // This is the entry point for thread. public void run() { try { for (int i = 5; i > 0; i--) { System.out.println(name + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(name + " interrupted."); } System.out.println(name + " exiting."); } } class DemoJoin { public static void main(Ssortingng args[]) { NewThread ob1 = new NewThread("One"); NewThread ob2 = new NewThread("Two"); NewThread ob3 = new NewThread("Three"); System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); // wait for threads to finish try { System.out.println("Waiting for threads to finish."); ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException e) { System.out.println("Main thread Interrupted"); } System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); System.out.println("Main thread exiting."); } } 

L’échantillon de sortie de ce programme est affiché ici:

 New thread: Thread[One,5,main] New thread: Thread[Two,5,main] New thread: Thread[Three,5,main] Thread One is alive: true Thread Two is alive: true Thread Three is alive: true Waiting for threads to finish. One: 5 Two: 5 Three: 5 One: 4 Two: 4 Three: 4 One: 3 Two: 3 Three: 3 One: 2 Two: 2 Three: 2 One: 1 Two: 1 Three: 1 Two exiting. Three exiting. One exiting. Thread One is alive: false Thread Two is alive: false Thread Three is alive: false Main thread Exiting 

Dans le code ci-dessus:

  1. Je ne suis pas en mesure de comprendre le déroulement de l’exécution du programme, et quand ob1 est créé, le constructeur est appelé où t.start() est écrit mais la méthode run() n’est toujours pas exécutée. Pourquoi cela se produit-il donc?

  2. join() méthode join() est utilisée pour attendre que le thread sur lequel elle est appelée ne se termine pas, mais ici en sortie on voit des sorties alternatives du thread pourquoi?

Et si l’utilisation de join est-ce alors quelle est l’utilisation de synchronized ??

Je sais qu’il me manque un concept de base, mais je ne peux pas le comprendre, alors aidez-moi.

Vous devez comprendre que la planification des threads est contrôlée par le programmateur de threads. Vous ne pouvez donc pas garantir l’ordre d’exécution des threads dans des circonstances normales.

Cependant, vous pouvez utiliser join() pour attendre qu’un thread termine son travail.

Par exemple, dans votre cas

 ob1.t.join(); 

Cette instruction ne sera pas renvoyée tant que le thread ne sera pas terminé.

Essaye ça,

 class Demo { Thread t = new Thread( new Runnable() { public void run () { //do something } } ); Thread t1 = new Thread( new Runnable() { public void run () { //do something } } ); t.start(); // Line 15 t.join(); // Line 16 t1.start(); } 

Dans l’exemple ci-dessus, votre thread principal s’exécute. Lorsqu’il rencontre la ligne 15, le thread t est disponible au planificateur de threads. Dès que le thread principal arrive à la ligne 16, il attend la fin du thread t .

t.join que t.join n’a rien fait pour t.join t ou pour t1 . Cela n’affectait que le thread qui l’appelait (c’est-à-dire le thread main() ).

Tout d’abord, lorsque vous créez ob1 le constructeur est appelé et il commence l’exécution. À ce moment, t.start() s’exécute également dans un thread séparé. N’oubliez pas qu’un nouveau thread est créé, il s’exécute parallèlement au thread principal. Et c’est la raison pour laquelle on commence à nouveau l’exécution avec l’instruction suivante.

Et l’instruction Join() est utilisée pour empêcher le thread enfant de devenir orphelin. Cela signifie que si vous n’avez pas appelé join() dans votre classe principale, alors le thread principal se fermera après son exécution et le thread enfant sera toujours en train d’exécuter les instructions. Join() attendra que tout le thread enfant termine son exécution et que seule la méthode principale se termine.

Passez en revue cet article, aide beaucoup.

Je ne suis pas en mesure de comprendre le déroulement de l’exécution du programme, et quand ob1 est créé, le constructeur est appelé où t.start () est écrit mais la méthode run () n’est toujours pas exécutée. Pourquoi cela se produit-il donc?

Cela dépend du Thread Scheduler en tant que partages principaux du même ordre de priorité. L’appel de start () ne signifie pas que run () sera appelé immédiatement, cela dépend du programmateur de thread lorsqu’il choisit d’exécuter votre thread.

La méthode join () est utilisée pour attendre que le thread sur lequel elle est appelée ne se termine pas, mais ici en sortie on voit des sorties alternatives du thread pourquoi?

C’est à cause du Thread.sleep (1000) dans votre code. Supprimez cette ligne et vous verrez ob1 se terminer avant ob2 qui à son tour se termine avant ob3 (comme prévu avec join ()). Cela dit, tout dépend du moment où ob1 ob2 et ob3 ont commencé. L’appel de veille mettra en pause l’exécution du thread pour> = 1 seconde (dans votre code), donnant au programmateur une chance d’appeler les autres threads en attente (même priorité).

Première règle du threading – “Threading is fun” …

Je ne suis pas en mesure de comprendre le déroulement de l’exécution du programme, et quand ob1 est créé, le constructeur est appelé où t.start() est écrit mais la méthode run() n’est toujours pas exécutée. Pourquoi cela se produit-il donc?

C’est exactement ce qui devrait arriver. Lorsque vous appelez Thread#start , le thread est créé et planifié pour l’exécution, cela peut arriver immédiatement (ou suffisamment près de lui), ce n’est peut-être pas le cas. Cela revient au programmateur de threads.

Cela dépend de la manière dont l’exécution du thread est planifiée et de ce qui se passe dans le système. Généralement, chaque thread aura un peu de temps pour s’exécuter avant d’être remis à “sleep” et un autre thread est autorisé à s’exécuter (évidemment dans plusieurs environnements de processeurs, plusieurs threads peuvent être exécutés à la fois, mais essayons et rest simple;))

Les threads peuvent également yield exécution, autoriser l’exécution d’autres threads du système.

Tu pourrais essayer

 NewThread(Ssortingng threadname) { name = threadname; t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread // Yield here Thread.yield(); } 

Et cela pourrait faire une différence dans la façon dont les threads s’exécutent … de la même manière, vous pourriez sleep pendant un court laps de temps, mais cela pourrait faire en sorte que votre thread soit ignoré pour une période de cycles (parfois vous le souhaitez, parfois vous n’avez pas) …

join() méthode join() est utilisée pour attendre que le thread sur lequel elle est appelée ne se termine pas, mais ici en sortie on voit des sorties alternatives du thread pourquoi?

La façon dont vous avez déclaré que la question est erronée … join attendra que le Thread soit appelé à mourir avant de revenir. Par exemple, si vous dépendez du résultat d’un Thread , vous pouvez utiliser la join pour savoir à quel moment le Thread est terminé avant d’essayer de récupérer son résultat.

De même, vous pouvez interroger le thread, mais cela va manger des cycles de CPU qui pourraient être mieux utilisés par le Thread place …

La JVM et le système d’exploitation sous-jacent disposent d’une liberté considérable lors de la planification des éléments. Le fait que vous obteniez tout le chemin pour “Attendre la fin des threads” avant de voir la sortie des threads individuels peut simplement signifier que le démarrage du thread prend un peu plus de temps (cela prend du temps entre le moment où un thread devient “”) alive “et lorsque la méthode run () commence réellement à s’exécuter). Vous pourriez voir la sortie de thread plus tôt mais ce n’est pas garanti dans les deux cas.

Quant à join () , cela garantit seulement que tout ce qui se passe après cela ne se produira qu’une fois que le thread que vous rejoignez est terminé. Donc, lorsque vous avez trois appels Join () consécutifs, cela ne signifie pas que les threads doivent se terminer dans un ordre particulier. Cela signifie simplement que vous allez d’abord attendre ob1 . Une fois ob1 terminé, ob2 et ob3 peuvent encore être en cours d’exécution ou être déjà terminés. S’ils sont terminés, vos autres appels à join () seront renvoyés immédiatement.

synchronized est utilisé spécifiquement lorsque plusieurs threads accèdent au même object et y apportent des modifications. Un bloc synchronisé est garanti pour ne jamais être exécuté par deux threads simultanément – c’est-à-dire que le thread qui l’exécute a l’object synchronisé tout seul.

Lorsque ob1 est créé, le constructeur est appelé là où “t.start ()” est écrit mais quand la méthode run () n’est toujours pas exécutée, la méthode main () est exécutée davantage. Pourquoi cela se produit-il donc?

Ici, vos threads et votre thread principal ont la même priorité. L’exécution du thread de priorité égale dépend totalement du Thread schedular Vous ne pouvez pas vous attendre à ce que l’exécution soit la première.

La méthode join () est utilisée pour attendre que le thread sur lequel elle est appelée ne se termine pas, mais ici en sortie on voit des sorties alternatives du thread pourquoi?

Ici, votre appel ci-dessous les déclarations de thread principal.

  ob1.t.join(); ob2.t.join(); ob3.t.join(); 

Donc, le thread principal attend que les threads ob1.t , ob2.t , ob3.t meurent (regardez dans Thread # join doc ). Ainsi, les trois threads s’exécutent avec succès et le thread principal se termine ensuite

Mes commentaires:

Quand je vois la sortie, la sortie est mélangée avec One, Two, Three, qui sont les noms des threads et ils s’exécutent simultanément. Je ne suis pas sûr quand vous dites que le thread ne fonctionne pas par la méthode principale.

Je ne sais pas si j’ai compris votre question ou non. Mais je réponds à ce que je pourrais comprendre, j’espère que cela pourra vous aider.

1) Ensuite, vous avez créé l’object, il a appelé le constructeur, dans la construction il a la méthode de démarrage qui a démarré le thread et exécuté le contenu écrit dans la méthode run ().

Alors que vous avez créé 3 objects (3 threads – un, deux, trois), les 3 threads ont commencé à s’exécuter simultanément.

2) Rejoindre et synchroniser Ce sont deux choses différentes. La synchronisation se produit lorsque plusieurs threads partagent une ressource commune et qu’un thread doit utiliser cette ressource à la fois. Par exemple, les threads tels que DepositThread, WithdrawThread, etc. partagent un object commun comme BankObject. Ainsi, pendant que DepositThread est en cours d’exécution, WithdrawThread attendra s’il est synchronisé. wait (), notify (), notifyAll () sont utilisés pour la communication inter-thread. Plz google pour en savoir plus.

à propos de Join (), c’est lorsque plusieurs threads sont en cours d’exécution, mais vous vous joignez. Par exemple, s’il y a deux threads t1 et t2 et que dans plusieurs envs ils s’exécutent, la sortie sera: t1-0 t2-0 t1-1 t2-1 t1-2 t2-2

et nous utilisons t1.join (), ce serait: t1-0 t1-1 t1-2 t2-0 t2-1 t2-2

Ceci est utilisé en temps réel lorsque parfois vous ne mélangez pas le thread dans certaines conditions et que l’une dépend d’une autre à compléter (pas dans une ressource partagée), vous pouvez donc appeler la méthode join ().

join () est une méthode d’instance de la classe java.lang.Thread que nous pouvons utiliser avec la méthode join () pour garantir que tous les threads qui ont démarré à partir de main doivent se terminer dans l’ordre dans lequel ils ont démarré. En d’autres termes, attend que ce fil meure.

Exception: la méthode join () lève InterruptedException.

Etat du thread: Lorsque la méthode join () est appelée sur le thread, elle passe de l’état d’attente à l’état d’attente. Et attendez que le fil meure.

bloc synchronisé: le thread n’a pas besoin d’acquérir un verrou d’object avant d’appeler la méthode join (). Par exemple, la méthode join () peut être appelée depuis un bloc externe synchronisé.

Temps d’attente: join (): attend que ce thread meure.

 public final void join() throws InterruptedException; 

Cette méthode appelle en interne join (0). Et timeout de 0 signifie attendre pour toujours;

join (long millis) – méthode synchronisée Attend au plus millis millisecondes que ce thread meure. Un timeout de 0 signifie attendre pour toujours.

 public final synchronized void join(long millis) throws InterruptedException; public final synchronized void join(long millis, int nanos) throws InterruptedException; 

Exemple de méthode de jointure

 class MyThread implements Runnable { public void run() { Ssortingng threadName = Thread.currentThread().getName(); Printer.print("run() method of "+threadName); for(int i=0;i<4;i++){ Printer.print("i="+i+" ,Thread="+threadName); } } } public class TestJoin { public static void main(String...args) throws InterruptedException { Printer.print("start main()..."); MyThread runnable = new MyThread(); Thread thread1=new Thread(runnable); Thread thread2=new Thread(runnable); thread1.start(); thread1.join(); thread2.start(); thread2.join(); Printer.print("end main()"); } } class Printer { public static void print(String str) { System.out.println(str); } } Output: start main()... run() method of Thread-0 i=0 ,Thread=Thread-0 i=1 ,Thread=Thread-0 i=2 ,Thread=Thread-0 i=3 ,Thread=Thread-0 run() method of Thread-1 i=0 ,Thread=Thread-1 i=1 ,Thread=Thread-1 i=2 ,Thread=Thread-1 i=3 ,Thread=Thread-1 end main() 

Note: appeler thread1.join () a fait le thread principal pour attendre que le thread-1 meure.

Vérifions un programme pour utiliser la jointure (millis longs)

Tout d'abord, la jointure (1000) sera appelée sur Thread-1, mais une fois 1000 millisecondes écastings, le thread principal pourra reprendre et démarrer le thread2 (le thread principal n'attendra pas la mort du Thread-1).

 class MyThread implements Runnable { public void run() { Ssortingng threadName = Thread.currentThread().getName(); Printer.print("run() method of "+threadName); for(int i=0;i<4;i++){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Printer.print("i="+i+" ,Thread="+threadName); } } } public class TestJoin { public static void main(String...args) throws InterruptedException { Printer.print("start main()..."); MyThread runnable = new MyThread(); Thread thread1=new Thread(runnable); Thread thread2=new Thread(runnable); thread1.start(); // once 1000 millisec are up, // main thread can resume and start thread2. thread1.join(1000); thread2.start(); thread2.join(); Printer.print("end main()"); } } class Printer { public static void print(String str) { System.out.println(str); } } Output: start main()... run() method of Thread-0 i=0 ,Thread=Thread-0 run() method of Thread-1 i=1 ,Thread=Thread-0 i=2 ,Thread=Thread-0 i=0 ,Thread=Thread-1 i=1 ,Thread=Thread-1 i=3 ,Thread=Thread-0 i=2 ,Thread=Thread-1 i=3 ,Thread=Thread-1 end main() 

Pour plus d'informations, consultez mon blog:

http://javaexplorer03.blogspot.in/2016/05/join-method-in-java.html

Pas de mots en cours d’exécution

 // Thread class public class MyThread extends Thread { Ssortingng result = null; public MyThread(Ssortingng name) { super(name); } public void run() { for (int i = 0; i < 1000; i++) { System.out.println("Hello from " + this.getName()); } result = "Bye from " + this.getName(); } 

}

Classe principale

 public class JoinRND { public static void main(Ssortingng[] args) { System.out.println("Show time"); // Creating threads MyThread m1 = new MyThread("Thread M1"); MyThread m2 = new MyThread("Thread M2"); MyThread m3 = new MyThread("Thread M3"); // Starting out Threads m1.start(); m2.start(); m3.start(); // Just checking current value of thread class variable System.out.println("M1 before: " + m1.result); System.out.println("M2 before: " + m2.result); System.out.println("M3 before: " + m3.result); // After starting all threads main is performing its own logic in // parallel to other threads for (int i = 0; i < 1000; i++) { System.out.println("Hello from Main"); } try { System.out .println("Main is waiting for other threads to get there task completed"); m1.join(); m2.join(); m3.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("M1 after" + m1.result); System.out.println("M2 after" + m2.result); System.out.println("M3 after" + m3.result); System.out.println("Show over"); } 

}

Le planificateur de threads est responsable de la planification des threads. Ainsi, chaque fois que vous exécutez le programme, il n’y a aucune garantie quant à l’ordre d’exécution des threads. Supposons que vous ayez un object thread nommé threadOne et si join () est appelé sur threadOne comme ceci:

threadOne.join ()

alors tous les threads en cours d’exécution seront mis en pause jusqu’à ce que le thread1 ait fini son exécution ou se termine.

Considérons le morceau de code suivant:

 class RunnableSample implements Runnable { private Thread t; private Ssortingng threadName; public RunnableSample(Ssortingng name) { this.threadName = name; } public void run() { try { for(int i = 4; i >= 1; i--) { System.out.println(Thread.currentThread().getName() + ", " + i); Thread.sleep(500); } } catch (InterruptedException e) { System.out.println(threadName + " interrupted"); } } public void start() { if(t == null) t = new Thread(this, threadName); t.start(); try { t.join(); } catch(Exception e) { System.out.println(e); } } } public class RunnableDemo { public static void main(Ssortingng[] args) { RunnableSample r1 = new RunnableSample("threadOne"); r1.start(); RunnableSample r2 = new RunnableSample("threadTwo"); r2.start(); RunnableSample r3 = new RunnableSample("threadThree"); r3.start(); } } 

Le résultat du programme ci-dessus sera:

 threadOne, 4 threadOne, 3 threadOne, 2 threadOne, 1 threadTwo, 4 threadTwo, 3 threadTwo, 2 threadTwo, 1 threadThree, 4 threadThree, 3 threadThree, 2 threadThree, 1 

Puisque join () est appelé en premier sur threadOne, threadTwo et threadThree seront suspendus jusqu’à ce que threadOne se termine. (Notez que threadOne, threadTwo et ThreadThree ont tous démarré). Maintenant, les threads s’exécutent dans un ordre spécifique. Si join () n’est pas appelé sur un thread dans notre exemple, alors il n’y aura pas d’ordre d’exécution des threads.

 public void start() { if(t == null) t = new Thread(this, threadName); t.start(); } 

Sa sortie sera:

 threadOne, 4 threadThree, 4 threadTwo, 4 threadTwo, 3 threadThree, 3 threadOne, 3 threadOne, 2 threadThree, 2 threadTwo, 2 threadOne, 1 threadThree, 1 threadTwo, 1 

Venir à la synchronisation, ce qui est utile si vous souhaitez contrôler l’access de plusieurs threads sur une ressource partagée. Si vous souhaitez restreindre un seul thread pour accéder aux ressources partagées, la synchronisation est le meilleur moyen de le faire.

Utiliser isAlive( ) et join( )

Souvent, nous voulons que le thread principal termine en dernier. Mais, comment un thread peut-il savoir quand l’autre thread est terminé?

 final boolean isAlive( ) final void join( ) throws InterruptedException 

join( ) méthode join( ) attendra qu’un thread termine son processus. Cette méthode attend que le thread sur lequel elle s’appelle se termine.

Son nom provient du concept selon lequel, le thread appelant attend que le thread spécifié le rejoigne. Des formes supplémentaires de join( ) vous permettent de spécifier une durée maximale pendant laquelle vous souhaitez attendre la fin du thread spécifié.

Voici une version améliorée de l’exemple précédent qui utilise join( ) pour s’assurer que le thread principal est le dernier à se terminer. Il montre également la méthode isAlive( ) .

 class NewThread implements Runnable { Ssortingng name; // name of thread Thread t; NewThread(Ssortingng threadname) { name = threadname; t = new Thread(this ,name); System.out.println("New thread: " + t); t.start(); // Start the thread } // This is the entry point for thread. @Override public void run() { try { for (int i = 5; i > 0; i--) { System.out.println(name + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(name + " interrupted."); } System.out.println(name + " exiting."); } } class DemoJoin { public static void main(Ssortingng args[]) { NewThread ob1 = new NewThread("One"); NewThread ob2 = new NewThread("Two"); NewThread ob3 = new NewThread("Three"); System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); // wait for threads to finish try { System.out.println("Waiting for threads to finish."); ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (Exception e) { System.out.println("Main thread Interrupted"); } System.out.println("Thread One is alive: " + ob1.t.isAlive()); System.out.println("Thread Two is alive: " + ob2.t.isAlive()); System.out.println("Thread Three is alive: " + ob3.t.isAlive()); System.out.println("Main thread exiting."); } }