CodeGym /Java Blog /Random-IT /Multithreading: cosa fanno i metodi della classe Thread
John Squirrels
Livello 41
San Francisco

Multithreading: cosa fanno i metodi della classe Thread

Pubblicato nel gruppo Random-IT
CIAO! Oggi continueremo a parlare di multithreading. Esaminiamo la classe Thread e cosa fanno alcuni dei suoi metodi. Quando abbiamo studiato i metodi di classe in precedenza, di solito scrivevamo solo questo: <nome metodo> -> <cosa fa il metodo>. Multithreading: cosa fanno i metodi della classe Thread - 1Questo non funzionerà con Threadi metodi di :) Hanno una logica più complessa che non sarai in grado di capire senza alcuni esempi.

Il metodo Thread.start()

Iniziamo ripetendoci. Come probabilmente ricorderai, puoi creare un thread facendo in modo che la tua classe erediti la Threadclasse e sovrascriva il run()metodo. Ma non si avvierà da solo, ovviamente. Per fare ciò, chiamiamo start()il metodo del nostro oggetto. Multithreading: cosa fanno i metodi della classe Thread - 2Ricordiamo l'esempio della lezione precedente:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Nota: per iniziare un thread, devi chiamare ilstart()metodo speciale piuttosto che ilrun()metodo! Questo è un errore facile da commettere, specialmente quando inizi a studiare il multithreading. Nel nostro esempio, se chiami ilrun()metodo 10 volte invece distart(), otterrai questo:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Guarda i risultati del nostro programma: Thread eseguito: Thread-0 Thread eseguito: Thread-1 Thread eseguito: Thread-2 Thread eseguito: Thread-3 Thread eseguito: Thread-4 Thread eseguito: Thread-5 Thread eseguito: Thread-6 Thread eseguito: Thread-7 Thread eseguito: Thread-8 Thread eseguito: Thread-9 Guarda l'ordine dell'output: Tutto sta accadendo in perfetto ordine. Strano, eh? Non siamo abituati a questo, perché sappiamo già che l'ordine in cui i thread vengono avviati ed eseguiti è determinato da un intelletto superiore all'interno del nostro sistema operativo: il thread scheduler. Forse siamo solo stati fortunati? Ovviamente non si tratta di fortuna. Puoi verificarlo eseguendo il programma un altro paio di volte. Il problema è che chiama ilrun()metodo direttamente non ha nulla a che fare con il multithreading. In questo caso, il programma verrà eseguito sul thread principale, lo stesso thread che esegue il main()metodo. Stampa semplicemente successivamente 10 righe sulla console e il gioco è fatto. 10 discussioni non sono state avviate. Quindi, ricordalo in futuro e controlla costantemente te stesso. Se vuoi che il run()metodo venga chiamato, chiama start(). Andiamo oltre.

Il metodo Thread.sleep()

Per sospendere l'esecuzione del thread corrente per un po', usiamo il sleep()metodo. Multithreading: cosa fanno i metodi della classe Thread - 3Il sleep()metodo accetta un numero di millisecondi come argomento, che indica la quantità di tempo per sospendere il thread.

public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

   }
}
Output della console: - Quanto tempo ho dormito? - 3 secondi Nota: il sleep()metodo è statico: dorme il thread corrente. Cioè, quello attualmente in esecuzione. Ecco un altro punto importante: un thread dormiente può essere interrotto. In questo caso, il programma genera un file InterruptedException. Prenderemo in considerazione un esempio di seguito. A proposito, cosa succede dopo che il thread si è svegliato? Continuerà ad essere eseguito proprio da dove era stato interrotto? No. Dopo che un thread si è svegliato, ovvero è trascorso il tempo passato come argomento a Thread.sleep(), passa a runnablestato. Ma questo non significa che lo scheduler dei thread lo eseguirà. Può molto probabilmente dare la preferenza a qualche altro thread non dormiente e consentire al nostro thread appena risvegliato di continuare il suo lavoro un po' più tardi. Assicurati di ricordare questo: svegliarsi non significa continuare a lavorare immediatamente!

Il metodo Thread.join()

Multithreading: cosa fanno i metodi della classe Thread - 4Il join()metodo sospende l'esecuzione del thread corrente fino al completamento di un altro thread. Se abbiamo 2 thread, t1e t2, e scriviamo

t1.join()
quindi t2non si avvierà finché t1non avrà terminato il suo lavoro. Il join()metodo può essere utilizzato per garantire l'ordine di esecuzione dei thread. Consideriamo come join()funziona il metodo nel seguente esempio:

public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
Abbiamo creato una ThreadExampleclasse semplice. Il suo compito è visualizzare un messaggio che il thread è iniziato, addormentarsi per 5 secondi e infine segnalare che il lavoro è completo. Pezzo di torta. La logica principale è nella Mainclasse. Guarda i commenti: usiamo il join()metodo per gestire con successo l'ordine di esecuzione dei thread. Se ricordi come abbiamo iniziato questo argomento, l'ordine di esecuzione è gestito dallo scheduler dei thread. Esegue i thread a sua discrezione: ogni volta in modo diverso. Qui stiamo usando il metodo per garantire che il t1thread venga prima avviato ed eseguito prima, poi il filet2thread, e solo dopo continuerà il thread principale del programma. Andare avanti. Nei programmi reali, troverai spesso situazioni in cui dovrai interrompere l'esecuzione di un thread. Ad esempio, il nostro thread è in esecuzione, ma è in attesa di un determinato evento o condizione. Se si verifica, il thread si interrompe. Probabilmente avrebbe senso se ci fosse una sorta di stop()metodo. Ma non è così semplice. C'era una volta, Java in realtà aveva un Thread.stop()metodo e consentiva l'interruzione di un thread. Ma è stato successivamente rimosso dalla libreria Java. Puoi trovarlo nella documentazione di Oracle e vedere che è contrassegnato come deprecato. Perché? Perché ha appena interrotto il thread senza fare nient'altro. Ad esempio, il thread potrebbe lavorare con i dati e modificare qualcosa. Poi, nel mezzo del suo lavoro, fu bruscamente e senza tante cerimonie interrotto dal stop()metodo. Senza un arresto adeguato, né il rilascio di risorse, nemmeno la gestione degli errori, non c'era niente di tutto questo. Per esagerare leggermente, il stop()metodo ha semplicemente distrutto tutto a suo modo. Era come staccare il cavo di alimentazione dalla presa per spegnere il computer. Sì, puoi ottenere il risultato desiderato. Ma tutti sanno che dopo un paio di settimane il computer non ti ringrazierà per averlo trattato in quel modo. Ecco perché la logica per l'interruzione dei thread è cambiata in Java e ora utilizza un interrupt()metodo speciale.

Il metodo Thread.interrupt()

Cosa succede se il interrupt()metodo viene chiamato su un thread? Ci sono 2 possibilità:
  1. Se l'oggetto era nello stato di attesa, ad esempio, a causa dei metodi joino sleep, l'attesa verrà interrotta e il programma lancerà un file InterruptedException.
  2. Se il thread era in uno stato funzionante, il interruptedflag booleano verrà impostato sull'oggetto.
Ma dobbiamo verificare il valore di questo flag sull'oggetto e completare correttamente il lavoro da soli! Ecco perché la Threadclasse ha il boolean isInterrupted()metodo. Torniamo all'esempio dell'orologio che era in una lezione del corso base. Per comodità, l'abbiamo semplificato leggermente:

public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
In questo caso, l'orologio viene avviato e inizia a ticchettare ogni secondo. Nel decimo secondo, interrompiamo il filo dell'orologio. Come già saprai, se il thread che stiamo tentando di interrompere è in uno degli stati di attesa, il risultato è un file InterruptedException. Questa è un'eccezione verificata, quindi possiamo facilmente individuarla ed eseguire la nostra logica per completare il programma. Ed è proprio quello che abbiamo fatto. Ecco il nostro risultato: Tick Tick Tick Tcik Tick Tick Tick Tick Il thread è stato interrotto Questo conclude la nostra introduzione ai Threadmetodi più importanti della classe. Buona fortuna!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION