Esercizi multithreading
1 - Possibili flussi
Dato il seguente codice:
class EsempioThread extends Thread {
public void run() {
System.out.println("THREAD_A");
System.out.println("THREAD_B");
System.out.println("THREAD_C");
System.out.println("THREAD_D");
System.out.println("THREAD_E");
}
public static void main(String[] args)
throws InterruptedException {
EsempioThread t1 = new EsempioThread();
t1.start();
// t1.join();
System.out.println("MAIN_A");
System.out.println("MAIN_B");
System.out.println("MAIN_C");
System.out.println("MAIN_D");
System.out.println("MAIN_E");
}
}
Quali sono i possibili flussi di esecuzione delle istruzioni?
Esempi di flussi possibili (il simbolo A < B vuol dire che l'istruzione A รจ eseguita prima di B):
MAIN_A < MAIN_B < MAIN_C < MAIN_D < THREAD_A < THREAD_B < THREAD_C < THREAD_D < THREAD_E < MAIN_E
MAIN_A < MAIN_B < THREAD_A < MAIN_C < THREAD_B < THREAD_C < MAIN_D < MAIN_E < THREAD_D < THREAD_E
THREAD_A < MAIN_A < THREAD_B < MAIN_B <THREAD_C < MAIN_C < THREAD_D < MAIN_D < THREAD_E < MAIN_E
Mentre ad esempio il seguente flusso non รจ possibile:
MAIN_A < THREAD_B < THREAD_A < MAIN_B < MAIN_D < MAIN_C < THREAD_C < THREAD_D < MAIN_E < THREAD_E
Vedi esempio:
class EsempioThreadMain {
static class EsempioThread extends Thread {
public void run() {
try {
System.out.println("THREAD_A");
sleep(10);
System.out.println("THREAD_B");
sleep(10);
System.out.println("THREAD_C");
sleep(10);
System.out.println("THREAD_D");
sleep(10);
System.out.println("THREAD_E");
sleep(10);
} catch (InterruptedException e) {}
}
}
public static void main(String[] args) throws InterruptedException {
EsempioThread t1 = new EsempioThread();
t1.start();
//t1.join();
System.out.println("MAIN_A");
Thread.sleep(10);
System.out.println("MAIN_B");
Thread.sleep(10);
System.out.println("MAIN_C");
Thread.sleep(10);
System.out.println("MAIN_D");
Thread.sleep(10);
System.out.println("MAIN_E");
Thread.sleep(10);
}
}
Nell'esempio sopra sono state aggiunte delle Thread.sleep()
tra le diverse println
, solo per aumentare il livello di concorrenza tra i thread e aumentare cosรฌ la variabilitร dell'output di esecuzione.
Esempi di output di due esecuzioni del programma EsempioThreadMain
:
PS C:\SCUOLA\RUN> javac .\EsempioThreadMain.java
PS C:\SCUOLA\RUN> java EsempioThreadMain
MAIN_A
THREAD_A
MAIN_B
MAIN_C
THREAD_C
THREAD_D
MAIN_D
THREAD_E
MAIN_E
PS C:\SCUOLA\RUN> java EsempioThreadMain
MAIN_A
THREAD_A
THREAD_B
MAIN_B
THREAD_C
MAIN_C
MAIN_D
THREAD_D
THREAD_E
MAIN_E
PS C:\SCUOLA\RUN>
Notate che l'output dell'esecuzione non รจ deterministico.
DOMANDA
Se togliamo il commento all'istruzione
t1.join()
nel codice delmain
dell'esempio sopra (riga 31), qual รจ l'output dell'esecuzione?Giustificate la vostra risposta.
2 - Creazione di thread contatore
Crea un'applicazione che abbia due contatori che in modo concorrente stampino a video il valore dalle propria variabile counter: uno parte da 0, poi 1, 2.... per 100 passi quindi fino a 99, l'altro contatore parte da 100, poi 101, 103 fino a 199 (sempre 100 passi). Facciamo inoltre che ogni contatore tra un numero e l'altro stampato a video, aspetti qualche centinaio di millisecondi, in modo da vedere meglio a video l'esecuzione contemporanea delle stampe a video dei due contatori e aumenti il livello di multiprogrammazione (suggerimento: utilizzate la sleep
della classe Thread
).
Qui lo pseudocodice del contatore:
// Some code
/*
startCounter variabile di tipo int che contiene il valore per iniziare
a contare.
100 sono i passi che compie il contatore dal punto di partenza.
*/
for (int i = startCounter; i < startCounter + 100; i++ ) {
System.out.println(i);
// sleep(400);
}

3 - Utilizzo di join
Fare un ulteriore versione che stampi un messaggio dal metodo main
quando i due thread hanno finito di stampare l'incremento del progressivo. Suggerimento: utilizzate il metodo join
della classe Thread
per sincronizzarsi con la fine dei due thread.

4 - Numero contatori generico
Generalizzare l'applicazione dell'esercizio 2 affinchรฉ sia possibile da riga di comando passare il numero di contatori da creare e il main thread aspetti che tutti i contatori abbiano finito attraverso il metodo join()
della classe Thread
. Dopo che tutti i thread hanno finito scrive a video il messaggio "FINE APPLICAZIONE".
5 - Interruzione di un thread in esecuzione
Scrivere un'applicazione che abbia un thread che in un ciclo infinito scriva a standard output un numero random diverso ad ogni ciclo. Utilizzate la classe standard
java.util.Random
per generare numeri random:
// Some code
long seed = System.currentTimeMillis();
Random random = new Random(seed);
// vedere ciclo infinito
while (true) {
int randValue = random.nextInt(1000);
System.out.println(randValue);
Thread.sleep(400);
}
Se dopo 10 secondi volessimo stopparlo come potremmo fare?
Suggerimento: utilizzate il metodo interrupt()
della classe Thread
.
2. Creare un'altra applicazione che prende da standard input il comando per stoppare l'applicazione quando lo desiderate.
Last updated