I metodi della classe Thread – Lezione 40 di Java Avanzato

I metodi di Thread: sleep, currentThread, join e interrupt

La classe Thread offre svariati metodi, oltre al metodo run e start che consentono rispettivamente di scrivere il corpo del thread e di farlo partire.

Il metodo statico sleep ha la funzione di mettere in attesa il thread corrente che chiama sleep per un dato numero di millisecondi. Se l’attesa di sleep viene interrotta il metodo lancia l’eccezione verificata InterruptedException. Si tratta di una caratteristica comune a tutti i metodi bloccanti, che mettono in attesa un thread e se vengono interrotti in modo anomalo lancia un’eccezione verificata.
L’intestazione del metodo sleep è la seguente:

  public static void sleep(long millis) throws InterruptedException

I metodi bloccanti lanciano un’eccezione di tipo verificato perchè è buona norma terminare il thread quando viene catturata un’eccezione, non bisogna mai ignorare una richiesta di terminazione. Se ci si trova nel metodo run di un thread, per terminare il thread corrente è sufficiente utilizzare return.

Un altro metodo molto utile della classe Thread è currentThread:

  public static Thread currentThread()

Questo metodo restituisce l’oggetto Thread corrispondente al thread di esecuzione che l’ha invocato, molto utile se si vogliono effettuare determinate operazioni sono in base all’effettivo thread in esecuzione.

  public final void join() throws InterruptedException

Il metodo join viene utilizzato per aspettare la terminazione di un thread, il metodo join mette in attesa il thread chiamante al thread da cui si invoca il metodo, se è già terminato ritorna direttamente. Anche join è un metodo bloccante quindi lancia un’eccezione verificata quando viene interrotto.

Vediamo un esempio, dati due thread t1 e t2 con t2 visibile in t1. Eseguendo quest’istruzione:

  t2.join();

Il metodo join mette in attesa il thread 1 fino alla terminazione del thread 2. Se al momento del’invocazione di join il thread 2 è già terminato ritorna immediatamente.

Interrompere un thread con interrupt e isInterrupted

Un thread termina quando il suo metodo run termina. Per interrompere le operazioni di un thread ogni thread è dotato di un flag booleano chiamato stato di interruzione, impostato inizialmente a false.
I metodi bloccanti, come sleep e join, vengono interrotti non appena lo stato di interruzione diventa vero.

Il metodo interrupt della classe Thread imposta a vero lo stato di interruzione del thread sul quale è invocato:

  public void interrupt()

Quindi, nonostante il suo nome possa fuorviare, interrupt non ha effetti diretti su un thread in esecuzione. Può essere visto come una richiesta di terminazione del thread mettendo il suo stato come “interrupted”. Il metodo stop(), adesso non può utilizzato, veniva utilizzato per la terminazione forzata dei thread. L’utilizzo di questo metodo è sconsigliato per evitare che il thread non rilasci risorse, ecc.

E’ possibile conoscere lo stato di interruzione di un thread chiamando il metodo isInterrupted:

  public boolean isInterrupted()

Questo metodo restituisce il valore attuale dello stato di interruzione del su cui è invocato.

Vediamo un esempio:

  public void run() {
    try {
      // ...
      while(...) {
        // ...
        Thread.sleep(tot); // Metto in attesa il thread di tot millisecondi
      }
    } catch(InterruptedException e) {
        return; // Come consigliato, termino il thread perchè interrotto
    } finally {
      // Libero le risorse
    }
  }

Un’applicazione dovrebbe sempre essere in grado di terminare su richiesta tutti i suoi thread. Per ottenere questo risultato, tutti i thread dovrebbero rispettare le seguente regole relative alle interruzioni:

  1. Se una chiamata bloccante lancia l’eccezione InterruptedException, il thread dovrebbe interpretarla come una richiesta di terminazione e quindi far terminare il thread;
  2. Se un thread non utilizza periodicamente chiamate bloccanti, dovrebbe invocare periodicamente il metodo isInterrupted e terminare se il risultato è vero.

Queste regole valgono in particolar modo per i thread con durata potenzialmente illimitata, come quelli basati su un ciclo infinito. In questo caso, invece di usare un’istruzione come while(true) è possibile utilizzare:

  while (!Thread.currentThread().isInterrupted()){...}

I Thread possono avere differenti priorità, l’assegnazione delle risorse da parte della JVM avviene secondo un schema preemptive quindi in base alla priorità dei thread. Ciascun thread inizialmente eredita la priorità dei thread genitore, che può essere cambiata tramite il metodo setPriority che può assegnare priorità con valori compresi tra MIN_PRIORITY e MAX_PRIORITY.

Indice Lezione PrecedenteLezione Successiva

Pubblicato in Guide, Java, Programmazione Taggato con: , , , , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*