Il ciclo di vita di un thread in Java è gestito dalla Java Virtual Machine (JVM) e i suoi stati sono definiti nell'enumerazione java.lang.Thread.State.
Sebbene la JVM utilizzi un set di stati predefiniti, dal punto di vista logico e di scheduling è utile distinguere tra la fase in cui un thread è pronto a girare e quella in cui occupa effettivamente la CPU.
Di seguito sono descritti i singoli stati e le transizioni che li collegano:
Un thread entra in questo stato non appena viene creata un'istanza della classe Thread (o di una sua sottoclasse) tramite l'operatore new.
In questa fase, il thread non è ancora "vivo" e il suo codice non ha iniziato l'esecuzione.
Dopo l'invocazione del metodo start(), il thread passa agli stati in cui può potenzialmente eseguire codice.
RUNNABLE (Pronto): Il thread è "eleggibile" per l'esecuzione.
Si trova in una coda di attesa (Coda Pronti) ed è pronto a utilizzare la CPU non appena il Thread Scheduler lo selezionerà .
RUNNING (In esecuzione): Questo stato si verifica quando lo scheduler assegna risorse di calcolo al thread.
In questa fase, il thread sta effettivamente eseguendo le istruzioni contenute nel suo metodo run().
Il passaggio tra questi due stati è dinamico: un thread in esecuzione può tornare in stato Runnable a causa di una preemption, della fine del suo quanto di tempo (time-slicing) o invocando il metodo yield(), che cede volontariamente la CPU ad altri thread di pari priorità .
Un thread può smettere temporaneamente di essere eseguibile per diversi motivi, entrando in uno stato di attesa o blocco:
BLOCKED (Bloccato): Il thread è in attesa di acquisire un monitor lock. Ciò accade tipicamente quando tenta di entrare in un metodo o un blocco marcato come synchronized che è attualmente occupato da un altro thread.
Il thread torna Runnable quando il monitor lock viene acquisito.
WAITING (In attesa): Il thread attende a tempo indefinito che un altro thread compia un'azione specifica.
Viene attivato da metodi come Object.wait() o Thread.join() (senza timeout).
Uscirà da questo stato, tornando nello stato Runnable, solo tramite una notifica esplicita (notify() o notifyAll()) o se il thread su cui ha fatto la join termina.
TIMED_WAITING (In attesa temporizzata): Simile al precedente, ma il thread attende solo per un periodo di tempo prefissato.
Viene innescato da metodi come Thread.sleep(ms), wait(timeout) o join(timeout).
Il thread torna Runnable allo scadere del tempo o alla ricezione di una notifica.
Un thread raggiunge questo stato finale quando il suo metodo run() completa l'esecuzione normalmente o viene interrotto da un'eccezione non gestita. Una volta terminato, un thread è considerato "morto" e non può essere riavviato.
new → NEW: Creazione dell'oggetto thread.
start() → RUNNABLE: Il thread diventa pronto all'esecuzione.
Scheduler → RUNNING: Assegnazione della CPU.
sleep() / wait(t) → TIMED_WAITING: Sospensione a tempo.
wait() / join() → WAITING: Attesa di un evento esterno.
Acquisizione lock → BLOCKED: Attesa di una sezione critica (synchronized).
Fine sospensione (TIMED_WAITING, WAITING o BLOCKED) → RUNNING
Fine run() → TERMINATED: Conclusione definitiva del ciclo di vita.