Multithreading in Java Fondamenti di Sistemi Informativi 2014 - 2015 Multithreading ● ● ● La programmazione concorrente consente di eseguire più processi o thread nello stesso momento. Nel secondo caso si parla di Multithreading Un thread è un sottoprocesso computazionale. I thread sono più leggeri dei processi e sfruttano una comunicazione a memoria condivisa Diversi thread contenuti nello stesso processo condividono alcune risorse (memoria e file aperti), mentre processi differenti non condividono le loro risorse Sistemi multiprocessore e multithreaded Un sistema multithreaded ha un singolo processore e il multithreading è generalmente implementato alternando l'esecuzione dei diversi thread in modo abbastanza frequente da dare all'utente la percezione che le attività siano eseguite allo stesso tempo. Multithreaded process http://en.wikipedia.org/wiki/File:Multithreaded_process.svg Mentre, in un sistema multiprocessore o multi-core, i thread possono essere eseguiti realmente in maniera concorrente, sfruttando ogni processore o core per eseguire diversi thread contemporaneamente. Alcuni Usi del multithreading ● ● Consente di velocizzare l'esecuzione dei programmi tramite parallelizzazione per sfruttare i moderni processori multi-core, condivisione di memoria e comunicazione fra thread più efficiente Consente di rendere più efficienti i programmi evitando che il flusso di esecuzione resti bloccato fino al termine di una attività, evento o rilascio di una risorsa. Per esempio è usato per realizzare applicazioni interattive implementando funzioni asincrone rispetto al normale flusso di esecuzione di un programma e web server che devono connettersi con più client contemporaneamente Multi-threading in Java I programmi Java possono essere multi-threaded. Le piattaforme Java implementano il timeslicing, che consente a più thread di condivedere un processore In base ai valori di priority Esistono due metodi per implementare il multi-threading ● estendendo la classe Thread ● implementando l'interfaccia Runnable Il primo metodo è più semplice del secondo, ma meno flessibile. Il secondo permette di definire Thread che estendono altre classi (in Java si può estendere solo una classe!) e di utilizzare meccanismi più avanzati per la schedulazione di Thread Metodo “thread” ● ● ● ● Il metodo più importante per la classe Thread è run(), che va sovrascritto per farlo comportare esattamente come vogliamo run( ) contiente il codice che sarà eseguito “simultaneamente” con gli altri thread in un programma il metodo start( ) nella classe Thread esegue delle operazioni di inizializzazione per il thread e poi chiama run( ) ATTENZIONE: è necessario sovrascrivere run() ma invocare start() che lancia il thread e ritorna immediatamente. Invocare direttamente il metodo run() blocca l'esecuzione del programma finché non termina run() Esempio metodo “thread” public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { HelloThread hello = new HelloThread(); hello.start(); } } Metodo “runnable” ● ● ● La nuova classe deve implementare l'interfaccia Runnable e può eventualmente estendere un'altra classe. Il metodo run() va implementato nello stesso modo. Per poter eseguire un oggetto Runnable è necessario istanziare la classe Thread e passare tale oggetto come parametro al costruttore Esempio metodo “runnable” public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { HelloRunnable hello = new HelloRunnable(); Thread t = new Thread( hello); t.start(); } } Altri metodi della classe Thread ● getName / getPriority restituisce nome/priorità del thread ● setName / setPriority ● sleep sospende l'esecuzione del thread per m millisecondi; ● ● modifica nome/priorità del thread yield sospende l'esecuzione del thread corrente consentendo l'esecuzione di altri thread pronti e a uguale priorità join attende la terminazione del thread per eseguire altri thread Synchronization ● ● ● La comunicazione fra thread avviene principalmente mediante condivisione di memoria, quindi accedendo agli stessi oggetti. È una forma di comunicazione estremamente efficiente, ma può causare problemi, fra cui: – Thread Interference, modifica dello stesso dato simultaneamente – Memory Consistency Errors, differenti thread hanno differenti viste dello stesso dato La sincronizzazione permette di prevenire tali problemi È possibile sincronizzare un metodo (Synchronized Methods) o blocchi di istruzioni (Synchronized Statements). Il secondo metodo consente di evitare di sincronizzare l'intero metodo e di specificare più precisamente quali oggetti sincronizzare migliorando la concorrenza con una sincronizzazione fine-grained (granularità più fine) Synchronized Methods public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } Fine-grained Synchronized Statements public class MsLunch { long c = 0; Object lock = new Object(); public void inc() { // qui potrebbero esserci altre istruzioni synchronized(lock1) { c++; } // anche qui potrebbero esserci altre istruzioni } } Sincronizzazione: uso del Monitor ● ● ● ● ● Il monitor permette di aggiungere una specifica della sincronizzazione fra i threads per mezzo dell’invocazione dei seguenti metodi: wait() rilascia il lock sull'oggetto e sospende il thread che lo invoca in attesa di una notifica. notifyAll() risveglia tutti i thread sospesi sull'oggetto in attesa di notifica. I thread risvegliati competono per acquisire il lock sull'oggetto. notify() risveglia un thread scelto casualmente tra quelli sospesi sull'oggetto in attesa di notifica. Il thread risvegliato compete per acquisire il lock sull'oggetto. Tali metodi devono essere invocati dall'interno di un metodo o blocco sincronizzato Alcuni link utili ● ● Java tutorial http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html Multi-threaded Client/Server Applications http://www.ase.md/~aursu/ClientServerThreads.html