Il metodo run ereditato dalla classe Thread non prevede parametri, ma può accedere
direttamente a tutti gli attributi della sottoclasse.
Per passare uno o più parametri a un thread, si dichiarano uno o più attributi,
e si definisce un costruttore con uno o più parametri in ingresso.
In questo modo i parametri possono essere passati al costruttore, il costruttore
inizializza gli attributi, e il metodo run può utilizzarli.
Scarica il progetto parametri.zip e completa il main della classe Test, utilizzando correttamente i costruttori dei thread Saluto e Contatore.
L'algoritmo di Euclide calcola il Massimo Comun Divisore (MCD) tra due numeri interi
a e b, senza bisogno di scomporli in fattori primi.
Scoperto più di 2300 anni fa, al giorno d'oggi il suo pseudocodice può essere scritto così:
while a ≠ b if a > b a ← a − b else b ← b − a return a
Se uno dei due numeri è molto più grande dell'altro (ad es. a ≅ 1012 e b ≅ 10),
l'algoritmo può impiegare più di un minuto per calcolare il risultato.
Per non far "congelare" il programma conviene eseguire il calcolo in background, delegandolo a un thread
secondo uno schema Master/Slave.
Il Master, che in questo corrisponde al main
Mentre ogni thread Slave
Scarica il progetto euclide.zip,
aggiungi alla classe Slave due attributi di tipo long, il costruttore appropriato e il metodo run,
e completa il metodo main della classe Master, gestendo l'input e avviando i thread all'interno di un ciclo infinito while(true){ }.
Simuliamo il lancio di due dadi con un programma in Java in cui ogni dado è un thread indipendente.
(int)(1+Math.random()*6);
Adele è una zia generosa che apre un conto corrente per quello spendaccione di suo nipote Bruno. In maniera indipendente l'uno dall'altro, Adele versa dei soldi sul conto e Bruno li preleva. Simuliamo questa situazione con un programma in Java in cui Adele e Bruno siano due thread che condividono la stessa risorsa, il conto.
Nel problema del Produttore/Consumatore (*) due thread si scambiano dati attraverso un buffer condiviso di dimensione finita. Il produttore genera i dati e li scrive nel buffer; il consumatore legge i dati dal buffer e li utilizza. Il problema è evitare che il produttore scriva un dato se il buffer è pieno, e che il consumatore legga un dato se il buffer è vuoto. Per semplicità in questo esercizio supporremo che il buffer abbia dimensione unitaria.
+----------+ +----------+ +----------+ | Producer | ===> | Buffer | ===> | Consumer | +----------+ +----------+ +----------+
(*) Il problema del produttore/consumatore si presenta spesso nella progettazione di sistemi informatici e di telecomunicazioni. Un esempio reale è un server che legge dati da un database e li invia a un client attraverso un canale di trasmissione, affidando i due compiti a thread indipendenti.