Se sei interessato a comprendere come la Java Virtual Machine (JVM) gestisca piรน thread in esecuzione contemporaneamente, questo articolo ti guiderร attraverso un esempio pratico. Modificheremo la classe EsempioThread per vedere il risultato dell’output a schermo relativo alla gestione dei thread.
Esempio di Classi Thread in Java
Iniziamo definendo la classe EsempioThread come illustrato nel seguente codice:
public class EsempioThread implements Runnable {
private int numeroThread;
public EsempioThread(int n) {
setNumeroThread(n);
}
public void setNumeroThread(int n) {
numeroThread = n;
}
public int getNumeroThread() {
return numeroThread;
}
public void run() {
for (int n = 0; n < 6; n++) {
System.out.println("*** thread numero " + getNumeroThread() + " in esecuzione");
System.out.println("l'indice n vale: " + n);
try {
Thread.sleep(1000);
} catch (InterruptedException exc) {
System.out.println("Errore durante il sonno del thread");
}
}
}
}
La variabile di classe numeroThread serve per identificare quale thread รจ in esecuzione. Il metodo Thread.sleep() sospende il thread per un tempo pari al valore passato come parametro, espresso in millisecondi. Inoltre, gestiamo l’eccezione di tipo InterruptedException utilizzando un blocco try-catch per garantire che il programma continui a funzionare senza interruzioni in caso di errore.
Implementazione di Thread Multipli
Adesso modifichiamo la classe di implementazione per lanciare due thread contemporaneamente:
public class Implementazione {
public static void main(String[] args) {
EsempioThread r1 = new EsempioThread(1);
EsempioThread r2 = new EsempioThread(2);
Thread nuovoThread1 = new Thread(r1);
Thread nuovoThread2 = new Thread(r2);
nuovoThread1.start();
nuovoThread2.start();
}
}
Passando i valori 1 e 2 al costruttore della classe EsempioThread, possiamo identificare i due thread durante l’esecuzione. L’output del programma, osservato durante alcune iterazioni, sarร simile al seguente:
*** thread numero 1 in esecuzione
l'indice n vale: 0
*** thread numero 2 in esecuzione
l'indice n vale: 0
*** thread numero 1 in esecuzione
l'indice n vale: 1
*** thread numero 2 in esecuzione
l'indice n vale: 1
Dall’output possiamo notare un importante vantaggio della programmazione con i thread: durante il blocco di un thread, l’altro thread puรฒ continuare la propria esecuzione. Senza l’uso dei thread, avremmo dovuto attendere che un thread completasse tutte le sue iterazioni prima di procedere con l’altro. Questo approccio sarebbe altamente inefficiente poichรฉ, per gran parte del tempo, l’applicazione rimarrebbe sospesa e la CPU inattiva.
Effetti della Rimozione di Thread.sleep()
Ricapitolando, nei nostri esempi, quando un thread viene sospeso, il controllo viene passato all’altro e viceversa. Ma cosa accade se eliminiamo il metodo sleep? Procediamo a modificare la classe EsempioThread rimuovendo il blocco try-catch e sostituendo il ciclo for con 400 iterazioni. Ecco il nuovo comportamento:
public void run() {
for (int n = 0; n < 400; n++) {
System.out.println("*** thread numero " + getNumeroThread() + " in esecuzione");
System.out.println("l'indice n vale: " + n);
}
}
Controllando l’output, noterai che il thread 1 inizia a stampare le proprie iterazioni, ma a un certo punto l’output sarร simile al seguente:
*** thread numero 1 in esecuzione
l'indice n vale: 273
*** thread numero 1 in esecuzione
l'indice n vale: 274
*** thread numero 2 in esecuzione
l'indice n vale: 0
Quello che รจ successo รจ che la JVM ha automaticamente sospeso il thread 1 per dare spazio al thread 2, il quale inizierร a eseguire le proprie iterazioni. Questo comportamento รจ noto come scheduling dei thread, ovvero la scelta dinamica di quale thread sospendere e quale attivare. Questo concetto รจ fondamentale nel multi-tasking dei sistemi operativi moderni e consente l’esecuzione simultanea di piรน programmi.
Infine, รจ importante capire che la decisione su quale thread sospendere dipende da numerosi fattori e puรฒ variare ad ogni esecuzione dell’applicazione. Pertanto, se rilanciamo il programma, non รจ garantito che il thread 1 si interrompa sempre all’iterazione 274, ma potrebbe farlo in un altro punto, a causa della presenza di altri processi in esecuzione sulla macchina.
Conclusioni e Prossimi Passi
Con quanto appreso in questa guida, ora hai gli strumenti necessari per creare applicazioni complesse e scalabili in Java. Dopo aver studiato la teoria, ricorda che la pratica รจ fondamentale: prova, sperimenta, commetti errori e correggili per evolvere come programmatore.