Concetto di Java Multithreading e metodo join ()

Sono confuso nel metodo join() usato in Threads in Java. Nel seguente codice:

 // Using join() to wait for threads to finish. class NewThread implements Runnable { String name; // name of thread Thread t; NewThread(String 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(String 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’output di esempio da questo programma è mostrato qui:

 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 

Nel codice precedente:

  1. Non sono in grado di capire il stream di esecuzione del programma, E quando viene creato ob1 il costruttore viene chiamato dove t.start() viene scritto ma ancora run() metodo non viene eseguito, piuttosto il metodo main() continua l’esecuzione. Allora perché sta succedendo questo?

  2. join() metodo join() è usato per aspettare fino a quando il thread su cui è chiamato non termina, ma qui in output vediamo output alternativi del thread perché ??

E se l’uso di join è questo allora qual è l’uso di synchronized ??

So che mi manca un concetto di base qui, ma non sono in grado di capirlo, quindi per favore aiutatemi.

È necessario comprendere che la pianificazione dei thread è controllata dallo scheduler dei thread. Pertanto, non è ansible garantire l’ordine di esecuzione dei thread in circostanze normali.

Tuttavia, puoi usare join() per aspettare che un thread completi il ​​suo lavoro.

Ad esempio, nel tuo caso

 ob1.t.join(); 

Questa dichiarazione non tornerà fino a quando il thread t ha finito di funzionare.

Prova questo,

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

Nell’esempio sopra, il thread principale è in esecuzione. Quando incontra la riga 15, il thread t è disponibile nell’utilità di pianificazione thread. Non appena il thread principale arriva alla riga 16, aspetterà che il thread t .

NOTA che t.join non ha fatto nulla per il thread t o per il thread t1 . Ha influito solo sul thread che lo ha chiamato (cioè il thread main() ).

Prima di tutto, quando crei ob1 viene chiamato il costruttore e inizia l’esecuzione. In quel momento t.start() viene eseguito anche in thread separati. Ricorda quando viene creato un nuovo thread, viene eseguito parallelamente al thread principale. E questo è il motivo per cui l’esecuzione principale inizia di nuovo con la prossima dichiarazione.

L’istruzione Join() viene utilizzata per impedire che il thread secondario diventi orfano. Significa che se non hai chiamato join() nella tua class principale, il thread principale uscirà dopo la sua esecuzione e il thread secondario sarà ancora lì ad eseguire le istruzioni. Join() attenderà fino a quando tutti i thread figlio completeranno l’esecuzione e solo il metodo main uscirà.

Passare attraverso questo articolo, aiuta molto.

Non sono in grado di capire il stream di esecuzione del programma, E quando viene creato ob1, il costruttore viene chiamato dove t.start () viene scritto ma ancora run () il metodo non viene eseguito, piuttosto il metodo main () continua l’esecuzione. Allora perché sta succedendo questo?

Questo dipende da Thread Scheduler poiché le condivisioni principali condividono lo stesso ordine di priorità. Chiamare start () non significa che run () verrà chiamato immediatamente, dipende dallo scheduler dei thread quando sceglie di eseguire il thread.

il metodo join () è usato per aspettare fino a quando il thread su cui è chiamato non termina, ma qui in output vediamo output alternativi del thread perché ??

Questo a causa del Thread.sleep (1000) nel codice. Rimuovi quella linea e vedrai le rifiniture di ob1 prima di ob2 che a sua volta termina prima di ob3 (come previsto con join ()). Detto questo dipende tutto da quando sono iniziati ob1 ob2 e ob3. Chiamando sleep si sospende l’esecuzione del thread per> = 1 secondo (nel codice), dando allo scheduler la possibilità di chiamare altri thread in attesa (stessa priorità).

Prima regola del threading: “Threading is fun” …

Non sono in grado di capire il stream di esecuzione del programma, E quando viene creato ob1, il costruttore viene chiamato dove t.start() viene scritto ma ancora run() metodo non viene eseguito, piuttosto il metodo main() continua l’esecuzione. Allora perché sta succedendo questo?

Questo è esattamente ciò che dovrebbe accadere. Quando chiami Thread#start , il thread viene creato e pianificato per l’esecuzione, potrebbe accadere immediatamente (o abbastanza vicino ad esso), potrebbe non farlo. Si tratta del programma di pianificazione dei thread.

Questo dipende da come è pianificata l’esecuzione del thread e da cosa sta succedendo nel sistema. In genere, a ogni thread verrà assegnata una piccola quantità di tempo per essere eseguito prima che venga ripristinato in “sleep” e un altro thread possa essere eseguito (ovviamente in più ambienti di processore, più thread possono essere eseguiti in tempo, ma proviamo e mantienilo semplice;))

I thread possono anche yield esecuzione, consentire ad altri thread nel sistema di avere la possibilità di eseguire.

Potresti provare

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

E potrebbe fare la differenza nel modo in cui i thread vengono eseguiti … allo stesso modo, potresti sleep per un breve periodo di tempo, ma questo potrebbe causare la trascuratezza del thread per l’esecuzione per un periodo di cicli (a volte lo vuoi, a volte non lo fai) …

join() metodo join() è usato per aspettare fino a quando il thread su cui è chiamato non termina, ma qui in output vediamo output alternativi del thread perché ??

Il modo in cui hai affermato che la domanda è sbagliata … join si aspetta che il Thread cui è chiamato sia morto prima di tornare. Ad esempio, se si dipende dal risultato di una Thread , è ansible utilizzare join per sapere quando la Thread è terminata prima di provare a recuperarne il risultato.

Allo stesso modo, è ansible eseguire il polling del thread, ma questo mangerà i cicli della CPU che potrebbero essere meglio utilizzati dal Thread invece …

La JVM e il sistema operativo sottostante hanno una notevole libertà quando si pianificano le cose. Il fatto che arrivi fino a “Attendere il completamento dei thread” prima di vedere l’output dei singoli thread può semplicemente significare che l’avvio del thread richiede un po ‘più di tempo (cioè richiede un po’ di tempo tra il momento in cui un thread diventa ” vivo “e quando il metodo run () inizia effettivamente l’esecuzione). Si potrebbe concepibilmente vedere l’uscita del filo prima, ma non è garantito in entrambi i modi.

Per quanto riguarda join () , garantisce solo che tutto ciò che è dopo si verificherà solo una volta che il thread che si sta unendo è fatto. Pertanto, quando si hanno tre chiamate join () in una riga, ciò non significa che i thread debbano terminare in un ordine particolare. Significa semplicemente che attendi prima ob1 . Una volta finito ob1 , ob2 e ob3 potrebbero essere ancora in esecuzione o potrebbero essere già finiti. Al termine, le altre chiamate join () verranno restituite immediatamente.

sincronizzato viene utilizzato in modo specifico quando più thread accedono allo stesso object e apportano modifiche ad esso. Un blocco sincronizzato è garantito che non viene mai eseguito da due thread contemporaneamente, cioè il thread che lo esegue ha l’object sincronizzato tutto per sé.

quando viene creato ob1, il costruttore viene chiamato dove viene scritto “t.start ()”, ma ancora run () il metodo non viene eseguito, piuttosto il metodo main () viene eseguito ulteriormente. Allora perché sta succedendo questo?

in questo caso i thread e il thread principale hanno uguale priorità. L’esecuzione di thread con uguale priorità dipende totalmente dalla Thread schedular del Thread schedular . Non puoi aspettarti quale eseguire prima.

il metodo join () è usato per aspettare fino a quando il thread su cui è chiamato non termina, ma qui in output vediamo output alternativi del thread perché ??

Qui la tua chiamata sotto le dichiarazioni dalla discussione principale.

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

Quindi il filo principale attende i thread ob1.t , ob2.t , ob3.t da morire (guarda in Thread # join doc ). Quindi tutti e tre i thread vengono eseguiti correttamente e il thread principale viene completato dopo

I miei commenti:

Quando vedo l’output, l’output è misto a One, Two, Three che sono i nomi dei thread e vengono eseguiti simultaneamente. Non sono sicuro quando dici che il thread non è in esecuzione con il metodo principale.

Non sono sicuro se ho capito la tua domanda o no. Ma sto mettendo la mia risposta su ciò che potrei capire, spero che possa aiutarti.

1) Poi hai creato l’object, ha chiamato il costruttore, in costruzione ha un metodo start che ha avviato il thread ed eseguito i contenuti scritti all’interno del metodo run ().

Così come hai creato 3 oggetti (3 thread – uno, due, tre), tutti e 3 i thread hanno iniziato l’esecuzione simultaneamente.

2) Join e sincronizzazione Sono due cose diverse, la sincronizzazione è quando ci sono più thread che condividono una risorsa comune e un thread dovrebbe usare quella risorsa alla volta. Ad es. Thread come DepositThread, WithdrawThread ecc. Condividono un object comune come BankObject. Quindi, mentre DepositThread è in esecuzione, il WithdrawThread attenderà se sono sincronizzati. wait (), notify (), notifyAll () vengono utilizzati per la comunicazione tra thread. Plz google per saperne di più.

su Join (), è quando più thread sono in esecuzione, ma ti unisci. ad esempio se ci sono due thread t1 e t2 e in multi-thread env corrono, l’output sarebbe: t1-0 t2-0 t1-1 t2-1 t1-2 t2-2

e usiamo t1.join (), sarebbe: t1-0 t1-1 t1-2 t2-0 t2-1 t2-2

Questo è usato in tempo reale quando a volte non si confonde il thread in determinate condizioni e si dipende da un altro per essere completato (non in una risorsa condivisa), quindi è ansible chiamare il metodo join ().

join () è un metodo di istanza della class java.lang.Thread che possiamo usare il metodo join () per garantire che tutti i thread avviati da main terminino nell’ordine in cui sono stati avviati e anche main dovrebbe finire in ultimo. In altre parole, aspetta che questo thread muoia.

Eccezione: il metodo join () genera InterruptedException.

Stato thread: quando viene chiamato il metodo join () sul thread, passa dallo stato di esecuzione allo stato di attesa. E aspetta che il thread muoia.

blocco sincronizzato: il thread non deve acquisire il blocco degli oggetti prima di chiamare il metodo join (), ad esempio il metodo join () può essere chiamato da un blocco sincronizzato esterno.

Tempo di attesa: join (): attende che questo thread muoia.

 public final void join() throws InterruptedException; 

Questo metodo chiama internamente join (0). E il timeout di 0 significa aspettare per sempre;

join (long millis) – metodo sincronizzato Attesa al massimo millisecondi perché questo thread muoia. Un timeout di 0 significa aspettare per sempre.

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

Esempio di metodo di join

 class MyThread implements Runnable { public void run() { String 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() 

Nota: chiamando thread1.join () fatto thread principale per attendere fino a quando Thread-1 muore.

Controlliamo un programma per usare join (long millis)

Innanzitutto, join (1000) sarà chiamato su Thread-1, ma una volta che 1000 millisec sono attivi, il thread principale può riprendere e avviare thread2 (il thread principale non aspetterà che Thread-1 muoia).

 class MyThread implements Runnable { public void run() { String 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() 

Per maggiori informazioni vedi il mio blog:

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

Non ci sono parole che eseguono il codice

 // Thread class public class MyThread extends Thread { String result = null; public MyThread(String 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(String[] 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"); } 

}

Lo scheduler dei thread è responsabile della pianificazione dei thread. Quindi ogni volta che esegui il programma, non c’è alcuna garanzia sull’ordine di esecuzione dei thread. Supponiamo di avere un object thread denominato threadOne e se join () viene chiamato su threadOne in questo modo:

threadOne.join ()

quindi tutti i thread attualmente in esecuzione verranno messi in pausa fino a quando thread1 ha terminato la sua esecuzione o termina.

Considera la seguente parte di codice:

 class RunnableSample implements Runnable { private Thread t; private String threadName; public RunnableSample(String 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(String[] args) { RunnableSample r1 = new RunnableSample("threadOne"); r1.start(); RunnableSample r2 = new RunnableSample("threadTwo"); r2.start(); RunnableSample r3 = new RunnableSample("threadThree"); r3.start(); } } 

L’output del programma di cui sopra sarà:

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

Poiché join () viene chiamato prima su threadOne, threadTwo e threadThree verranno messi in pausa fino al termine di threadOne. (NOTA che threadOne, threadTwo e ThreadThree sono stati tutti avviati). Ora i thread sono in esecuzione in un ordine specifico. Se join () non viene chiamato su un thread nel nostro esempio, non ci sarà alcun ordine di esecuzione dei thread.

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

La sua produzione sarà:

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

Venendo alla sincronizzazione, che è utile se si desidera controllare l’accesso di più thread su qualsiasi risorsa condivisa. Se si desidera limitare solo un thread per accedere alle risorse condivise, la sincronizzazione è il modo migliore per farlo.

Usare isAlive( ) e join( )

Spesso vorremmo che il thread principale finisse per ultimo. Ma come può sapere un thread quando l’altro thread è terminato?

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

metodo join( ) , attenderà che un thread finisca il suo processo. Questo metodo attende finché il thread su cui è chiamato termina.

Il suo nome deriva dal concetto che, il thread chiamante attende fino a quando il thread specificato lo unisce. Forme aggiuntive di join( ) consentono di specificare la quantità massima di tempo che si desidera attendere per il termine del thread specificato.

Ecco una versione migliorata dell’esempio precedente che utilizza join( ) per garantire che il thread principale sia l’ultimo da terminare. Dimostra anche il metodo isAlive( ) .

 class NewThread implements Runnable { String name; // name of thread Thread t; NewThread(String 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(String 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."); } }