JavaThread
JavaThread
PROCESSI
Facoltà di Ingegneria
Nei sistemi concorrenti (multiprogrammati), il termine processo
denota la singola attività eseguita in modo indipendente e
separato rispetto alle altre.
• Tipicamente, un programma è eseguito da un processo.
CORSO DI
• Il processo è l'istanza in esecuzione di un processo
• Più processi possono eseguire lo stesso programma.
RETI DI CALCOLATORI Paragone con Classi e Oggetti: un programma agisce come una
Linguaggio Java: i Thread classe, il processo rappresenta una instanza in esecuzione del
programma.
Un processo:
Prof. Franco Zambonelli
• è del tutto autonomo e indipendente dagli altri processi
Lucidi realizzati in collaborazione con • ha un prorpio spazio di indirizzamento riservato (porzione di
Ing. Enrico Denti - Univ. Bologna memoria RAM) e non condivide memoria con altri processi:
significa che anche le variabili globali sono private al processo
• ha un proprio stack riservato (quindi anche le variabili locale
sono private al processo).
La comunicazione tra processi distinti non può quindi avvenire in
modo “diretto” (per condivisione di variabili), ma deve sfruttare
appositi meccanismi di sistema (p.e., file o socket).
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 1 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 2
ESEMPIO THREAD
Quando da una finestra lancio un server, e poi da un'altra Spesso si vogliono realizzare programmi in cui non vi è solo una
finestra lancio un client, questi due programmi in attività in esecuzione, ma in cui diverse attività in concorrenza
esecuzione sono processi diversi, e non possono interagire eseguono (motivi di efficienza dell'esecuzione). In questo caso, vi
se non tramite la scrittura di parti comuni di file o attraverso è può l'esigenza forte di fare interagire le diverse attività in
comunicazione via socket!!! esecuzione.
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 3 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 4
LA CLASSE Thread
THREAD IN JAVA
La classe Thread è la base per la gestione dei thread in Java.
Come si può realizzare il concetto di Thread in Java?
Essa comprende metodi per attivare, fermare, sospendere,
NEL MODO PIU' NATURALE! Sono oggetti particolari ai quali riprendere, attendere thread, per controllarne la priorità, lo
si richiede un servizio (chiamato start()) corrispondente al scheduling, etc.
lancio di una attività, di un thread! MA: non si aspetta che il
servizio termini, esso procede in concorrenza a chi lo ha richiesto!
Il corpo del thread è costituito dal metodo run()
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 5 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 6
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 7 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 8
ESEMPIO CONTROLLO DEI THREAD
• un thread continua la propria esecuzione o fino alla sua
terminazione naturale, o fino a che o fino a che non viene
Creazione di un thread tramite l’interfaccia Runnable
espressamente fermato da un altro thread che invochi su di esso
La nuova classe di thread… il metodo stop()
class MyBody3 implements Runnable {
// NON DERIVA DA Thread! • un thread può anche essere sospeso temporaneamente dalla sua
esecuzione
public void run(){
for(int i=1; i<=10; i++) • perché un operazione blocca l'esecuzione, come una
System.out.println(i + " " + i*i); operazione di input che implica di attendere dei dati. Il
} Thread si blocca finchè i dati non sono disponibili.
} • perché invoca la funzione Thread.sleep();
… e la corrispondente classe di test che lo crea e lo attiva: • da un altro thread che invochi su di esso il metodo
suspend(), per riprendere poi la propria esecuzione
public class Esempio3 { quando qualcuno invoca su di esso il metodo resume().
public static void main(String args[]){
MyBody3 b3 = new MyBody3(); La classe di thread opportunamente modificata…
Thread t = new Thread(b3);
// o anche: class MyThread2 extends Thread {
// Thread t = new Thread(new MyBody3()); public void run(){
for(int i=1; true; i++) // ciclo infinito
t.start(); System.out.println(i + " " + i*i);
} }}
}
… e la corrispondente classe di test che crea e gestisce il thread:
public class Esempio2 {
public static void main(String args[]){
MyThread2 t2 = new MyThread2();
t2.start();
Thread.sleep(1000); // sleeps 1 sec
t2.suspend();
Thread.sleep(1500); // sleeps 1,5 sec
t2.resume();
Thread.sleep(300); // sleeps 0,3 sec
t2.stop();
}}
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 9 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 10
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 11 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 12
ESEMPIO DI JOIN UNA VARIANTE:
Creazione di una serie di thread con nome in sequenza
Creazione di una serie di thread in sequenza
class Esempio4 { class Esempio4bis {
public static void main(String args[]){ public static void main(String args[]){
System.out.println("Main - inizio"); System.out.println("Main - inizio");
while(true) { int i=1;
MyThread4 t = new MyThread4(b4); while(true) {
System.out.print("new " + Thread t = new MyThread4("Enrico" + i++);
(t==null ? "fallita" : "riuscita")); System.out.print("new " +
System.out.println(" (CTRL-C per finire)"); (t==null ? "fallita" : "riuscita"));
t.start(); System.out.println(" (CTRL-C per finire)");
try { t.start();
t.join(); // attende che t termini try {
} t.join(); // attende che t termini
catch(InterruptedException e) {} }
} } } catch(InterruptedException e) {}
} }}
class MyThread4 extends Thread {
public void run(){ class MyThread4 extends Threads {
System.out.println("Qui thread " + public void run(){
Thread.currentThread().getName() ); System.out.println("Qui thread " +
} Thread.currentThread().getName() );
} }}
NOTE: NOTA:
• il main è un ciclo infinito che crea continuamente nuovi thread • la classe Thread ha sia un costruttore con un solo argomento
(fino a che non viene chiuso con CTRL-C) (che si aspetta un oggetto che implementi Runnable) sia uno
• prima di creare un nuovo thread, il main attende, tramite con due argomenti, che all’oggetto Runnable affianca un
join(), che termini quello precedentemente in esecuzione oggetto String che si assume essere il nome del thread.
• l’attesa di join() potrebbe essere interrotta da un’eccezione
→ necessità di try/catch
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 13 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 14
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 15 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 16
COROUTINING INTERAZIONE TRA THREAD
Indipendentemente dalla politica di scheduling dei adotata dalla
macchina virtuale, è facile in Java costruire due thread che si Supponiamo di avere questa classe di Thread
cedono reciprocamente il controllo (schema cosiddetto di co-
class ThreadCC extends Thread {
routining) Counter c;
int i;
public ThreadCC(Counter cc)
ESEMPIO 6 - Esempio di coroutining fra due thread { c = cc; }
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 17 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 18
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 19 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 20
SEZIONI CRITICHE ESEMPIO – Conto Corrente
Sincronizzato
Le sezioni di codice in cui si accede a risorse e oggetti comuni
(condivise) sono critiche: per evitare inconsistenze, è necessario
assicurare che, prima di entrarvi, i thread si sincronizzino, in Public class CC {
modo da garantire che solo un thread per volta possa eseguire la Int totale_conto;
…
sezione critica. Nell'esempio precedente, bisogna evitare che due public synchronized void versamento(int importo)
thread eseguano in concorrenza in metodo versamento. { int nuovo_totale; //variabile locale
nuovo_totale = totale_conto + importo - tasse;
In Java si può garantire l’accesso in mutua esclusione a una totale_conto = nuovo_totale;
istanza, proteggendo il metodo o la sezione di codice critica }
tramite la keyword synchronized: }
• metodo sincronizzato:
class ThreadCC extends Thread {
public synchronized void setValue() {...} CC c;
Solo un thread alla volta può eseguire questo metodo sullo public ThreadCC(CC cc)
{ c = cc; }
stesso oggetto.
• sezione di codice sincronizzata: public void run(){
for( i=1; i<=10; i++)
synchronized(object) {...} cc.versamento(i*1000);
Solo un thread alla volta può eseguire la parte di codice }}}
protetta sull’oggetto object (che può essere this).
public class EsempioCC {
Nell'esempio precedente: public static void main(String args[]){
• il metodo versamento deve essere synchronized CC c = new CC();
ThreadCC t1 = new ThreadCC(c);
• mentre il flusso di esecuzione di un thread esegue tale metodo, ThreadCC t2 = new ThreadCC(c);
è garantito che nessun'altro thread potrà eseguirlo t1.start();
t2.start(); }}
• se Thread A sta già esegunedo il metodo, quando Thread B
tenta di eseguirlo viene sospeso, in attesa che Thread A termini
• quando Thread A termina, Thread B riprende l'esecuzione a può
eseguire il metodo versamento.
NESSUNA INCONSISTENZA!!!!!
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 21 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 22
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 23 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 24
ESEMPIO - Uso dello stack I THREADS NELLA PROGRAMMAZIONE
public class Esempio9 { DI RETE
public static void main(String args[]){
// creo tre istanze configurate diversamente I threads risultano fondamentali per avere programmi di rete
MyBody9 b1 = new MyBody9("pusher"); efficienti e flessibili
MyBody9 b2 = new MyBody9("popper");
MyBody9 b3 = new MyBody9("printer");
// creo tre thread, uno per task da eseguire PROBLEMA BASE:
Thread t1 = new Thread(b1, "Produttore"); Quando un server sta svolgendo il suo servizio per uno specifico
Thread t2 = new Thread(b2, "Consumatore"); cliente, non può accettare richieste di connessione da altri clienti
Thread t3 = new Thread(b3, "Visualizzatore"); SOLUZIONE:
// ora attivo Produttore e Consumatore… il server, quando deve fornire un servizio, non lo fa lui. Invece,
t2.start(); crea un thread il quale è delegato a svolgere il servizio. Il server,
t1.start(); di per sé, può rimanere in ascolto di ulteriori richieste di
// …e aspetto che finiscano entrambi connessioni e servirle
try { t1.join(); }
catch(InterruptedException e1) {} ALTRI PROBLEMI:
try { t2.join(); } Le operazioni di lettura, scrittura, e di attesa connessioni sono
catch(InterruptedException e2) {} operazioni bloccanti. Se non c’è chi scrive, legge, o si connette, il
// alla fine attivo il Visualizzatore programma non fa nient’altro che aspettare. Magari potrebbe
t3.start();
eseguire altri pezzi del programma utili.
} SOLUZIONE:
} Creare più thread, lasciare un thread in attesa nelle operazioni
NOTA: bloccanti, mentre gli altri thread vanno avanti con il programma.
• a rigore, esiste ancora un rischio di inconsistenza sugli oggetti
memorizzati nello stack, in quanto si memorizzano riferimenti: CORRELATO A CIO’:
altri thread potrebbero fare riferimento agli stessi oggetti, e In molti casi, i programmi di rete agiscono sia da clienti che da
modificarli mentre sono memorizzati nello stack servitori, ed è bene che le due cose possano svolgersi in modo
• sarebbe più sicuro archiviare nello stack delle copie (cloni) indipendente….così la parte servitore è sempre disponibile a
degli oggetti anziché mantenere dei riferimenti servire e la parte cliente può continuare a chiedere altri servizi…
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 25 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 26
Franco Zambonelli, Enrico Denti - THREAD IN JAVA 27 Franco Zambonelli, Enrico Denti - THREAD IN JAVA 28
ESEMPIO:TIMER CONCORRENTE