i thread in java - digilander.libero.it · • il multithreading è estremamente diffuso (es....
TRANSCRIPT
I Thread in Java
L20_MultiThread 2
Thread e Task• Multitasking: capacità dei sistemi operativi di
eseguire più programmi contemporaneamente. Ciascun programma ha il proprio insieme di variabili, costanti, ecc.
Multithreading capacità dei programmi di eseguire, al loro interno, più task (thread) contemporaneamente. Un programma è multithread se il thread principale lancia almeno un thread secondario. I thread condividono le variabili, le classi del programma, lo spazio di indirizzamento, ha execution stack (stack delle chiamate) e program counter (indirizzo prox istruzione) privati.
L20_MultiThread 3
• Il multithreading è estremamente diffuso (es. browser che caricano più immagini contemporaneamente, o più pagine), la gestione delle richieste concorrenti da parte di un web service o un application server. Lo stesso meccanismo di garbage collecting è svolto tramite un thread
• Con JAVA 5 la gestione dei thread è stata completamente rivista ed arricchita, soprattutto dal punto di vista del sincronismo. Java offre degli strumenti che facilitano l'utilizzo dei thread, rispetto ad altri linguaggi di programmazione.
L20_MultiThread 4
I thread sono caratterizzati dal loro stato
• ESECUZIONE• PRONTO PER L'ESECUZIONE: in attesa di essere
eseguito dalla CPU • SOSPESO• RIPRESO dal punto in cui era stato sospeso • BLOCCATO quando attende una risorsa; • TERMINATO
L20_MultiThread 5
La priorità dei thread
La priorità del thread stabilisce l’importanza del trhead rispetto gli altri. La CPU privilegia il thread a maggiore priorità quando deve assegnare tempo di esecuzione ai vari thread. Un thread a priorità più alta può anche terminare un thread a priorità più bassa Il thread principale. Un programma Java possiede un thread di esecuzione, che è il thread principale. In esso si generano gli altri thread per i programmi multithread. Quando il thread thread principale termina, lo stesso programma termina.
L20_MultiThread 6
Scheduling dei thread
La JVM determina il tempo di esecuzione di ciascun thread con l'algoritmo FIXED PRIORITY SCHEDULING
• Un thread in esecuzione viene interrotto dallo scheduler quando:Un thread con priorità più alta diventa runnable;Il metodo run termina l’esecuzione o il threadesegue un yield;
• Quando la porzione di tempo (quanto) di tempo assegnato dallo scheduler si è esaurito (non tutti i sistemi operativi - devono supportare il “time slicing”)
L20_MultiThread 7
Creazione di un thread in Java
Java offre due possibilità di creazione di un thread:
• una istanza di un oggetto che estende l’oggetto thread (package java.lang.*).
• una istanza di un oggetto che implementa l’interfaccia runnable
L20_MultiThread 8
• Il codice del thread (il task del thread) deve essere inserito nel metodo “run”Nella classe Thread l’implementazione del suo metodo run è vuota.Per attivare il thread si invoca il metodo start() che a sua volta invoca il metodo run() (che può essere chiamato solo attraverso start())
Primo caso: sottoclasse di Thread
L20_MultiThread 9
class MyThread extends Thread { public MyThread(String str) { super(str); } public void run() { for (int i=0;i<10;i++) { System.out.println(getName()+"it: "+i); try { sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println(getName()+" finito!"); } } public class test{ public static void main (String[] args){ MyThread t1=new MyThread("uno"); MyThread t2=new MyThread("due"); t1.start();//attivazione del thread t1 t2.start();//attivazione del thread t2}}//= QUANTI THREAD CONCORRENTI COESISTONO in questo esempio ?
L20_MultiThread 10
Metodi della classe Thread
resume Riprende l’esecuzione di un thread sospeso
run Contiene il codice eseguibile del tread
sleep(ms) Sospende il thread per un tempo definito di ms millesecondi
start Avvia il thread invocando il codice di esecuzione
stop Forza la terminazione ell’esecuzione di unthread. Tutte le risorse del thread vengonoliberate (anche i lock), attraverso la propagazione dell’eccezione ThreadDeath
join blocca il thread chiamante in attesa dellaterminazione del thread di cui si invoca il metodo.
suspend Sospente indefinatemente il thread
L20_MultiThread 11
Interrompere un Thread
• Un thread termina quando il suo metodo run termina. Il metodo stop() per la terminazione forzata e’ stato deprecato, per scoraggiarne l'uso (evitare che il thread non rilasci risorse, ecc).
• Il metodo interrupt è usato per richedere la terminazione di un Thread, che viene messo nello stato “interrupted”
• I thread dovrebbero di tanto in tanto controllare se sono in uno stato interrupted.
L20_MultiThread 12
Lo stato interrupted non è una richiesta mandatoria di terminazione,
ma va interpretato caso per caso (verifica altre condizioni chiusura), eccTIPICA IMPLEMENTAZIONE
• public void run(){ try { //== while (!Thread.currentThread().isInterrupted() && more work to do) { do more work } } catch(InterruptedException e) { // thread was interrupted during sleep or wait } finally { cleanup, if required } // exiting the run method terminates the thread }
L20_MultiThread 13
Il metodo sleep solleva la InterruptedException se viene invocato quando è in uno strato interrupted. In questo caso non c'è bisogno di considerare lo stato Interrupted
public void run(){ try { . . . while (more work to do) { do more work Thread.sleep(delay); } } catch(InterruptedException e) { // thread was interrupted during sleep or wait } finally { cleanup, if required } // exiting the run method terminates the thread}
L20_MultiThread 14
Altri metodiinterrupt() Mette il trhead nello stato booleano interrupt
static boolean interrupted()
Verifica che il thread è stato messo in uno stato interrupted. L’invocazione del metodo resetta lo stato interrupted a false
boolean isInterrupted()
Verifica che il thread è stato messo in uno stato interrupted. L’invocazione del metodo NON resetta lo stato interrupted
currentThread() Restituisce il thread corrente (statico)
L20_MultiThread 15
Il thread principale
Il metodo currentThread restituisce il riferimento al thread corrente. Se lanciato all’interno del programma principale da il riferimento al thread principale
public class MainThread { public static void main(String args[]) { Thread t = Thread.currentThread(); t.setName(“Main Thread"); t.setPriority(1); try { t.sleep(10000); } } catch (InterruptedException e) { System.out.println("Thread interrotto"); } } }
L20_MultiThread 16
L’interfaccia “runnable”
• Con Interfaccia Runnable è possibile creare threadcome sottoclasse di qualsiasi altra classe (non solo di Thread)
• Il codice eseguibile va inserito nel metodo run() nella classe che implementa l’interfaccia Runnable
• Si deve creare un’istanza della classe• Si deve creare un’istanza della classe Thread passando
come parametro l’istanza della classe che si è creata
• Per lanciare il thread si deve invocare il metodo start() sul thread creato producendo la chiamata al metodo run()
L20_MultiThread 17
class MyRunnable extends MyClass implements Runnable{// MyClass è una classe qualsiasi (non sottoclasse di thread)
public void run(){
for (int i=1; i<=100; i++)System.out.println( “CICLO ” + i);
}}public class ExRunnable{
public static void main(String args[]){
MyRunnable e = new MyRunnable();Thread t = new Thread(e);t.start();
}}
L20_MultiThread 18
Thread e priorità
• L’assegnazione delle risorse da parte della JVM avviene secondo un schema “preemptive”, in base alla priorità dei thread.
• Ciascun thread eredita la priorità dei thread genitore. La priorità si può cambiare tramite il metodo setPriority
• La priorità varia tra MIN_PRIORITY o MAX_PRIORITY
L20_MultiThread 19
La sincronizzazione
In molte situazioni, i thread devono condividere risorse ed accedere agli stessi oggetti. Accedendo contemporaneamente agli stessi oggetti, due o più thread possono procurare effetti incontrollati sullo stato degli oggetti
L20_MultiThread 20
Allo stesso modo i metodi stop() e suspend() dei thread possono generare situazioni iconsistenti o blocchi critici.
I Thread possono, all’atto della sospensione impegnare una risorsa in modo esclusivo, generando situazioni inconsistenti o di blocco critico (deadlock)
L20_MultiThread 21
A partire dalla JDK vers. 1.4, i metodi stop(), suspend() e resume() sono diventati “deprecated” (sconsigliati), pur rimanendo presenti per retro compatibilità.
Le azioni di controllo e sincronizzazione fra thread si devono più propriamente realizzare tramite i metodi wait(), notify(), notifyAll() e gli object locks.
L20_MultiThread 22
• I thread condividono uno spazio comune di indirizzamento, e l’interazione può avvenire tramite oggetti comuni, che sono:
1)Object locks -> i thread si autoescludono (interazione competitiva)
2)Variabili -> interazione cooperativa
3)Metodi di sincronizzazione
L20_MultiThread 23
Lock
• I thread gestiscono le risorse comuni attraverso i lock assimilabili ai semafori del C.
• Si individuano alcune sezioni di codice che operano su un oggetto come sezioni critiche (la parola chiave synchronized).
• Il compilatore, in corrispondenza della sezione critica inserisce una intestazione (header), ed un epilogo (alla fine), in questo modo implementa il lock associato all’oggetto riferito dalla sezione critica
L20_MultiThread 24
Il codice della sezione critica viene eseguito se il lock è in stato libero, altrimenti il thread rimane in attesa. Gli oggetti che vogliono accede all’oggetto, sono inseriti in una tabella dalla JVM, e via via accedono all’oggetto non appena viene rilasciato dai vari thread
Esempio:Object mutex_Lock= new Object();
public void A( ) {…;synchronized (mutex_Lock){… /* codice sezione critica */;}…;}
L20_MultiThread 25
Il codice della blocco sincronizzato viene eseguito in maniera esclusiva da un thread
• Non ci possono essere altre esecuzioni dello stesso blocco
• Non ci possono essere esecuzione di altri blocchi sincronizzati sullo stesso oggetto
L20_MultiThread 26
Metodi synchronized
E’ possibile definire alcuni metodi sincronized, assicurandone la loro mutua esclusione
public class intVar {private int i=0;public synchronized void incrementa(){ i ++; }public synchronized void decrementa(){i--; }}L’esecuzione del metodo avviene in mutua esclusione
utilizzando il lock dell’oggetto.
L20_MultiThread 27
I metodi wait e notify
• La sincronizzazione tra i thread puo’ avvenire anche con i metodi wait e notify
• I metodi wait interagiscono con il “wait set”, coda di thread associati ad un oggetto
• Gli oggetti entrano ed escono nel wait set con i metodi wait e notify, che possono essere invocati all’interno di un blocco syncronized
L20_MultiThread 28
wait rilascia il lock, sospende il e lo inserisce in wait set.
notify Estrae il thread dal wait
set e lo inserisce nel entry set. NON RILASCIA IL LOCK
notifyall Estrae tutti i thread dal wait set e li inserisce nell’entry set
NON rilascia il lockLIMITAZIONI
• unica coda (wait set) per ogni oggetto sincronizzato• non e` possibile sospendere thread su code differenti!
L20_MultiThread 29
public class IntBox {private int[]contenuto;private int contatore, testa, coda;public IntBox(){ //==ctr
contenuto = new int[10];contatore = 0;testa = 0;coda = 0;
}public synchronized int preleva (){
int elemento;while (contatore == 0) wait();elemento = contenuto[testa];testa = (testa + 1)%10;--contatore;notifyAll();return elemento;
}public synchronized void deposita (int valore){
while (contatore == 10)wait();contenuto[coda] = valore;coda = (coda + 1)%10;++contatore;notifyAll();
}}
L20_MultiThread 30
Implementazione di un semaforo binario
• Java non prevede i semafori come nel C, ma possono essere implementati con i metodi di sincronizzazione
public class Semaphore {private int value;public Semaphore (int initial){value = initial;}synchronized public void V()//signal sul semaforo{ ++value;
notify();}synchronized public void P() throws InterruptedException //wait{
{ while (value == 0) wait();--value;
}}
L20_MultiThread 31
Interfaccia ConditionIn Java 5 sono state introdotte le interface condition e lock che
permettono di estendere il meccanismo wait/notify e di esplicitare il lock
public interface Condition{void await ()throws InterruptedException;void signal();void signalAll();
}public interface Lock{
//Public instance methodsvoid lock();void unlock();Condition newCondition();
}• I metodi await, signal, e signalAll sono equivalenti ai
metodi wait, notify e notify_all, riferiti alla coda di processi associata alla condition sulla quale vengono invocati)
L20_MultiThread 32
• Ad ogni variabile condizione è associato un lock
• al momento della sospensione del thread mediante await viene liberato;
• al risveglio di un thread viene occupato.• La creazione di una condition avviene col
metodo newCondition del lock associato ad essa.
Lock lockvar=new Mylock(); //Mylock è una classe che implementa//l’interfaccia LockCondition C=lockvar.newCondition();
L20_MultiThread 33
Equivalenza tra meccanismo lock e syncronizedpublic void method(){ implicitLock.lock(); try {
//method body } finally { implicitLock.unlock(); }}
public synchronized void method(){ //method body}/*(es)*/
L20_MultiThread 34
DeadLock• Possono verificarsi delle situazioni applicative in cui la
concorrenza dei thread può bloccare l'elaborazione. E' il caso in cui un thread entra in una sezione critica di un metodo A, al cui interno c'è' l'invocazione di un metodo sincronizzato B, che a sua volta invoca il metodo A.
• Due thread che accedono al metodo A e B possono mutuamente bloccarsi, perché aspettano l'uscita dell'altro dalla sezione critica
• Non c'è un meccanismo effettivo per evitare i deadlock, né strumenti offerti da Java. Si devono escludere possibili situazioni di deadlock applicativamente
L20_MultiThread 35
Blocking Queue• Le blocking queue sono code tipo FIFO speciali
con le due operazioni fondamentali (aggiungere un elemento in coda e rimuovere quello in testa), con la proprietà di bloccare i thread che vi accedono per aggiungere elementi quando la coda è piena, o quando cercano di rimuovere e la coda è vuota.
• In questo modo si dispone di un meccanismo di sincronizzazione dei thread e di bilanciamento del carico tra i therad
L20_MultiThread 36
metodo Ok KO
add Aggiunge un elemento alla lista Eccezione IllegalStateException se la coda è piena
remove Rimuove e restituisce l'elemento top della lista
Eccezione NoSuchElementException se la coda è vuota
element Restituisce l'elemento top della lista Eccezione NoSuchElementException se la coda è vuota
offer Aggiunge un elemento e restituisce true
Restituisce null se la coda è piena
poll Rimuove e restituisce l'elemento top della lista
Restituisce null se la coda è vuota
peek Restituisce l'elemento top della lista Restituisce null se la coda è vuota
put Aggiunge un elemento alla lista Blocca la coda se è piena
take Rimuve e restituisce l'elemento top della lista
Blocca la coda se è vuota
Metodi di blockqueue
L20_MultiThread 37
Thread safe collection• Quando due thread contemporaneamente
accedono ad una collection, possono danneggiare la collection, produrre stati inconsistenti.
• E' possibile richiedere l'accesso esclusivo con dei meccanismi di sincronizzazione
• Il package java.util.concurrent offre delle efficienti implementazioni di collection che thread safe, che consentono a diversi thread di accedere contemporaneamente alla struttura (fino a 16)
L20_MultiThread 38
• L'effetto si ottiene attraverso sofisticati algoritmi che regolano l'accesso ed iteratori di tipo “weak” che possono non tenere conto delle ultime modifiche alla struttura
• Esempio: ConcurrentHashMap
L20_MultiThread 39
Interfacce Callable e Future• L'interfaccia callable è simile alla Runnable solo che
prevede che venga restituito un valorepublic interface Callable<V>{ V call() throws Exception;}
• L'interfaccia Future puo' essere usata per lanciare una computazione (asincrona), ed ottenere il risultato successivamente
•public interface Future<V>{ V get() throws . . .; V get(long timeout, TimeUnit unit) throws . . .; void cancel(boolean mayInterrupt); boolean isCancelled(); boolean isDone();}
L20_MultiThread 40
Thread Pools• Java fornisce dei meccanismi (classi Executors) per
gestire thread pool. In questo modo il numero di thread creati è controllato (con minore dispendio di risorse)
newFixedThreadPool Pool di thread fisso e mantenuti in idle indefinitamente.
newCachedThreadPool I thread sono creati quando necessario, e mantenuti in idle per 60 sec.
newSingleThreadExecutor Un pool costituito da un solo thread che svolge i supoi compiti sequenzialmente
newScheduledThreadPool Pool fisso per esecuzioni schedulate
newSingleThreadScheduledExecutor Single thread per l'esecuzione schedulata
L20_MultiThread 41
SyncronizersIl package java.util.concurrent dispone di una serie di oggetti specializzati nella sincronizzazione
classe Cosa fa Quando usarla
CyclicBarrier Fa in modo che un certo numero di thread aspettano il compimento delle azioni di tutti gli altri, quindi esegue una azione opzionale (barrier action)
Quando è necessario aspettare che i thread abbiamo finito la loro azione per passare alla successiva
CountDownLatch Mette in attesa un set di thread fino a che un contatore raggiunge il valore 0
Quando è necessario che un tread aspetti un certo risultato per entrare in azione
Exchanger Fa in modo che due thread si scambino un oggetto quando sono pronti per farlo
Quando due trhead devono condividere una istanza modificando i suoi valori
SynchronousQueue Fare in modo che due thread possono scambiarsi degli oggetti, quando entrambi sono pronti per farlo. Quando un thread invoca put sulla coda, si blocca fino a che un altro thread invoca take
A differenza di exchanger, lo scambio dati è unidirezionale
Semaphore Blocca i thread fino a che è possibile procedere
Agendo sul numero di permit, consente di limitare l'accesso a risorse ad un numero di thread alla volta Se permit =1 l'accesso è consentito solo se un altro thread ad il permesso