JavaRush /Java Blog /Random-IT /Multithreading: cosa fanno i metodi della classe thread

Multithreading: cosa fanno i metodi della classe thread

Pubblicato nel gruppo Random-IT
Ciao! Oggi continuiamo a parlare di multithreading. Diamo un'occhiata alla classe Thread e al funzionamento dei suoi diversi metodi. In precedenza, quando studiavamo i metodi delle classi, molto spesso li scrivevamo semplicemente in questo modo: “nome del metodo” -> “cosa fa”.
Multithreading: cosa fanno i metodi della classe Thread - 1
Questo non funzionerà con i metodi Thread :) La loro logica è più complicata e senza diversi esempi è impossibile capirla.

Metodo Thread.start()

Cominciamo con la ripetizione. Come probabilmente ricorderai, puoi creare un thread ereditando la tua classe dalla classe Threade sovrascrivendo il metodo in essa contenuto run(). Ma, ovviamente, non inizierà da solo. Per fare ciò, chiamiamo il metodo sul nostro oggetto start(). 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("Выполнен поток " + 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 avviare una discussione, è necessario chiamare il metodo specialestart(), non il metodorun()! Questo è un errore facile da commettere, soprattutto quando si impara per la prima volta il multithreading. Se nel nostro esempio chiami un metodo su un oggetto 10 volterun()invece distart(), il risultato sarà così:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
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 thread eseguito Guarda la sequenza di output: tutto procede rigorosamente in ordine. Strano, vero? Non siamo abituati a questo, perché sappiamo già che l'ordine in cui i thread vengono avviati ed eseguiti è determinato dalla superintelligenza all'interno del nostro sistema operativo: lo scheduler dei thread. Forse sono stato solo fortunato? Naturalmente non è una questione di fortuna. Puoi verificarlo eseguendo il programma ancora un paio di volte. Il punto è che chiamare direttamente un metodorun()non ha nulla a che fare con il multithreading. In questo caso, il programma verrà eseguito nel thread principale, quello in cui viene eseguito il metodomain(). Trasmetterà semplicemente 10 linee in sequenza alla console e il gioco è fatto. Non verranno avviati 10 thread. Pertanto, ricorda per il futuro e controlla te stesso costantemente. Se vuoi che venga fattorun(), chiamalostart(). Andiamo avanti.

Metodo Thread.sleep()

Per mettere in pausa l'esecuzione del thread corrente per un po' di tempo, utilizzare il comando sleep(). Multithreading: cosa fanno i metodi della classe Thread - 3Il metodo sleep()prende come parametro il numero di millisecondi, ovvero il tempo durante il quale il thread deve essere messo in stop.
public class Main {

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

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
Output della console: - Quanto ho dormito? - 3 secondi Nota: il metodo sleep()è statico: mette in stop il thread corrente. Cioè quello che sta funzionando in questo momento. Un'altra sfumatura importante: il flusso nello stato di sonno può essere interrotto. In questo caso, si verificherà un'eccezione nel programma InterruptedException. Di seguito vedremo un esempio. A proposito, cosa succede dopo che il thread si è “risvegliato”? Continuerà immediatamente la sua esecuzione da dove si era interrotta? NO. Dopo che il thread si è riattivato, quando scade il tempo trascorso come argomento Thread.sleep(), entra nello stato eseguibile . Tuttavia, ciò non significa che lo scheduler del thread lo eseguirà. È del tutto possibile che darà la preferenza a qualche altro thread "non dormiente", e il nostro thread "appena risvegliato" continuerà a funzionare un po' più tardi. Assicurati di ricordare: "svegliarsi non significa continuare a lavorare proprio in quel preciso istante!"

Metodo Thread.join()

Multithreading: cosa fanno i metodi della classe Thread - 4Il metodo join()sospende l'esecuzione del thread corrente fino al completamento di un altro thread. Se abbiamo 2 thread, t1e t2, e scriviamo -
t1.join()
t2non inizierà a funzionare finché t1 non avrà completato il suo lavoro. Il metodo join()può essere utilizzato per garantire la sequenza di esecuzione dei thread. Consideriamo il lavoro join()utilizzando un esempio:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

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

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

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, How будет завершен
       (or бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, How t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончor работу, программа завершена");

   }
}
Abbiamo creato una classe semplice ThreadExample. Il suo compito è visualizzare sullo schermo un messaggio sull'inizio del lavoro, quindi addormentarsi per 5 secondi e alla fine informare del completamento del lavoro. Niente di complicato. La logica principale è contenuta nella classe Main. Guarda i commenti: utilizzando il metodo, join()controlliamo con successo la sequenza di esecuzione dei thread. Se ricordi l'inizio dell'argomento, lo scheduler del thread ha fatto questo. Li ha lanciati a sua discrezione: ogni volta in modo diverso. Qui, utilizzando il metodo, ci siamo assicurati che prima venisse avviato ed eseguito il thread t1, poi il thread t2e solo dopo il thread principale di esecuzione del programma. Andare avanti. Nei programmi reali, incontrerai spesso situazioni in cui devi interrompere l'esecuzione di alcuni thread. Ad esempio, il nostro thread è in esecuzione, ma è in attesa che venga soddisfatto un determinato evento o condizione. Se ciò accade, si ferma. Probabilmente sarebbe logico se esistesse un metodo come stop(). Tuttavia, tutto non è così semplice. C'era una volta un metodo Thread.stop()in Java che permetteva di interrompere il lavoro di un thread. Ma in seguito è stato rimosso dalla libreria Java. Puoi cercarlo nella documentazione di Oracle e vedere che è contrassegnato come deprecato . Perché? Perché ha semplicemente interrotto il flusso senza alcun lavoro aggiuntivo. Ad esempio, un thread potrebbe funzionare con i dati e modificare qualcosa al loro interno. Poi è stato improvvisamente messo fuori combattimento stop()nel bel mezzo del lavoro - e basta. Non c'è stato uno shutdown corretto, nessuna liberazione di risorse, nessuna gestione degli errori: niente di tutto questo è successo. Il metodo stop(), per esagerare, ha semplicemente distrutto tutto sul suo cammino. Il suo funzionamento può essere paragonato a come qualcuno stacca la spina dalla presa per spegnere un computer. Sì, puoi ottenere il risultato desiderato. Ma tutti capiscono che tra un paio di settimane il computer non dirà "grazie" per questo. Per questo motivo, la logica per l'interruzione dei thread in Java è stata modificata e ora viene utilizzato un metodo speciale: interrupt().

Metodo Thread.interrupt()

Cosa succede se chiami un metodo interrupt() su un thread ? Ci sono 2 opzioni:
  1. Se in quel momento l'oggetto era nello stato di attesa, ad esempio, joino sleep, l'attesa verrà interrotta e il programma lancerà InterruptedException.
  2. Se il thread era in uno stato funzionante in quel momento, verrà impostato il flag booleano dell'oggetto interrupted.
Ma dovremo controllare l'oggetto per il valore di questa bandiera e completare noi stessi correttamente il lavoro! A questo scopo, la classe Threadha un metodo speciale: boolean isInterrupted(). Torniamo all'esempio dell'orologio della lezione del corso principale. Per comodità si semplifica 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("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
Nel nostro caso, l'orologio si avvia e inizia a ticchettare ogni secondo. Al 10° secondo interrompiamo il flusso dell'orologio. Come già sai, se il thread che stiamo tentando di interrompere è in uno degli stati di attesa, il risultato sarà InterruptedException. Questo tipo di eccezione è un'eccezione controllata, quindi può essere facilmente intercettata ed eseguita la logica di terminazione del programma. Questo è quello che abbiamo fatto. Ecco il nostro risultato: Tik Tik Tik Tik Tik Tik Tik Tik Tik Il lavoro del thread è stato interrotto e con questo si conclude la nostra introduzione ai metodi principali della classe Thread. Per consolidare le tue conoscenze, puoi guardare questa lezione video sul multithreading:
servirà come ottimo materiale aggiuntivo! Alla fine, dopo una panoramica dei metodi, viene spiegato esattamente cosa approfondiremo nel corso :) Buona fortuna!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION