# Esercizi multithreading

### 1 - Possibili flussi&#x20;

Dato il seguente codice:

```java
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):&#x20;

* `MAIN_A < MAIN_B < MAIN_C < MAIN_D < THREAD_A < THREAD_B < THREAD_C < THREAD_D < THREAD_E < MAIN_E`&#x20;
* `MAIN_A < MAIN_B < THREAD_A < MAIN_C < THREAD_B < THREAD_C < MAIN_D < MAIN_E < THREAD_D < THREAD_E`&#x20;
* `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:

{% code lineNumbers="true" %}

```java

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);

  }
}

```

{% endcode %}

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 del `main` dell'esempio sopra (riga 31), qual è l'output dell'esecuzione?&#x20;
>
> 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`).&#x20;

&#x20;Qui lo pseudocodice del contatore:

```java
// 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);
}

```

![Activity diagram - flusso esecuzione dell'applicazione](https://3264574854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVU7WiFKajQhwsnAlGh%2Fuploads%2FqvO1je7ecMOl2BtYFHa3%2FAppContatori-Page-1%20\(1\).png?alt=media\&token=c3781c4d-ed85-44fe-a66b-6f40513f28ab)

### 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.*

![Activity diagram - flusso esecuzione dell'applicazione](https://3264574854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LVU7WiFKajQhwsnAlGh%2Fuploads%2Fvf9P16VLe4Is8CTbxM2V%2FAppContatori-Copy%20of%20Page-1%20\(1\).png?alt=media\&token=6f88ed88-fffd-4cfb-bc96-f4b14d3efe50)

### 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

1. Scrivere un'applicazione che abbia un thread che in un ciclo infinito scriva a *standard outpu*t un numero random diverso ad ogni ciclo. Utilizzate la classe standard `java.util.Random` per generare numeri random:

```java
// 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?&#x20;

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.
