Programmazione concorrente in Java



Documenti analoghi
Java Virtual Machine

Multithreading in Java. Fondamenti di Sistemi Informativi

Java threads (2) Programmazione Concorrente

T 1. Per un processo con più thread di controllo, lo stato di avanzamento della computazione di ogni thread è dato da:

Gestione dei thread in Java LSO 2008

Esercitazione 2: Java Thread. Java Thread. Java Thread. Un thread:

SAPIENZA Università di Roma Facoltà di Ingegneria dell Informazione, Informatica e Statistica

Java thread, concorrenza

Un esercizio d esame. Flavio De Paoli

GESTIONE DEI PROCESSI

Programmazione Concorrente in Java

Threads in Java. I threads. Costruttori. Prof.ssa Sara Michelangeli

Ottava Esercitazione. introduzione ai thread java mutua esclusione

Con il pulsante Start si introducono palline che rimbalzano in un area di disegno fino a che non è terminato il loro ciclo di vita (1000 movimenti).

Esercizi sugli Oggetti Monitor

Telematica II 17. Esercitazione/Laboratorio 6

Il costrutto monitor [Hoare 74]

Appunti di Sistemi Operativi. Enzo Mumolo address web address : Introduzione ai processi - concorrenza

19. Introduzione al multi-threading

Esercitazioni 7 e 8. Bounded Buffer con sincronizzazione Java (1)

Esercizi sul Monitor in Java

Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A lezione 14 - Thread in Java

Laboratorio di Sistemi Thread Java

Terza Esercitazione. Unix - Esercizio 1. Unix System Call Exec Java Introduzione Thread

Il costrutto monitor [Hoare 74]

Java Threads. esempi

Programmazione concorrente con il linguaggio Java

Definizione di thread Proprietà dei thread in Java Gestione delle priorità nei programmi multithreaded Gruppi di thread Accesso a variabili condivise

Synchronized (ancora)

Concorrenza e sincronizzazione

Programmazione concorrente in Java. Dr. Paolo Casoto, Ph.D

Esercitazioni Ingegneria del So2ware 8 Threads. Giordano Tamburrelli tamburrelli@elet.polimi.it h@p://giordano.webfacdonal.com

Thread e Task. L20_MultiThread 2

Sincronizzazione dei Thread in Java. Daniela Tibaldi:

Sincronizzazione dei Thread in Java

Sincronizzazione con Java

Thread in Java CAPITOLO Richiami di gestione di processi

progam ponteasensounicoalaternato ; type dir = ( nord, sud );

PROCESSI ESEMPIO THREAD. RETI DI CALCOLATORI Linguaggio Java: i Thread CORSO DI. Università degli Studi di Modena e Reggio Emilia

Esercizio Sincronizzazione Thread

Monitor. Introduzione. Struttura di un TDA Monitor

Un programma concorrente è un programma nel quale diverse computazioni possono essere eseguite allo stesso tempo Alcuni sistemi sono implicitamente

SISTEMI OPERATIVI. Sincronizzazione in Java (Monitor e variabili condizione in Java)

Lezione 15 Programmazione multithreaded

Corso di Programmazione Concorrente. Java Thread. Valter Crescenzi

SISTEMI OPERATIVI. Sincronizzazione in Java (Semafori e barriere) Patrizia Scandurra (MODULO DI INFORMATICA II) LABORATORIO

La concorrenza in Java package java.util.concurrent Antonio Furone

Java Virtual Machine. Indipendenza di java dalla macchina ospite. I threads in Java

8. Java: Eccezioni e Thread

Programmazione concorrente e threads

Sistemi Operativi. Lez. 13: primitive per la concorrenza monitor e messaggi

Multithreading in Java

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

La gestione dell input/output da tastiera La gestione dell input/output da file La gestione delle eccezioni

Il costrutto monitor

Informatica 3. Informatica 3. LEZIONE 6: Il controllo dell esecuzione. Lezione 6 - Modulo 1. Errori durante l esecuzione. Il controllo dell esecuzione

Esercizio monitor. Sistemi Operativi T 1

Algoritmi di Ricerca. Esempi di programmi Java

Sistemi Operativi. Processi GESTIONE DEI PROCESSI. Concetto di Processo. Scheduling di Processi. Operazioni su Processi. Processi Cooperanti

Chat. Si ha un server in ascolto sulla porta Quando un client richiede la connessione, il server risponde con: Connessione accettata.

Sistemi Operativi Esercizi Sincronizzazione

Esercizi della lezione 5 di Java

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

RMI Remote Method Invocation

Java: Compilatore e Interprete

Corso di Linguaggi di Programmazione

Transcript:

Programmazione concorrente in Java

Multithreading in Java Ogni thread e un oggetto, creato come istanza della classe java.lang.thread La classe Thread contiene tutti i metodi per gestire i threads L utente implementa il metodo run() Uno dei metodi piu importanti e il metodo start() che lancia il thread utilizzando il metodo run definito dall utente Ogni istanza di Thread deve quindi essere associata ad un metodo run Ci sono due metodi per realizzare un thread: Implementando l interfaccia Runnable L'interfaccia contiene il solo metodo public void run() Estendendo la classe java.lang.thread e sovrascrivendo il metodo run() Un thread termina quando Finisce Viene eseguito il metodo stop() del thread Scatta una eccezione Lo scheduling e effettuato tramite le priorita (metodo setpriority()) A parita di priorita round-robin

Multithreading in Java Creazione ed esecuzione di un Thread in Java: Thread t = new Thread(); t.start(); Questo thread non ha codice e si ferma subito. Come si indica il codice del Thread? Ci sono due modi: Mediante creazione subclass: public class MioThread extends Thread { System.out.println("Sono MioThread "); MioThread t = new MioThread(); t.start(); Mediante implementazione classe Runnable public class MioRunnable implements Runnable { System.out.println("Sono MioRunnable "); Thread t = new Thread(new MioRunnable()); t.start();

Multithreading mediante creazione subclass 1 import java.io.*; public class PingPong2{ // il main crea e lancia i thread public static void main(string[] a){ Ping2 c=new Ping2(); c.start(); Pong2 t=new Pong2(); t.start(); class Ping2 extends Thread{ try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); class Pong2 extends Thread{ try{ Thread.sleep(990); catch (InterruptedException e){ System.out.println("\tPong");

Multithreading mediante creazione subclass 2 import java.io.*; public class PingPong3{ public static void main(string[] a){ Ping3 c=new Ping3(); Pong3 t=new Pong3(); class Ping3 extends Thread{ //ogni thread si lancia da solo try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); Ping3(){ start(); class Pong3 extends Thread{ try{ Thread.sleep(990); catch (InterruptedException e){ System.out.println("\tPong"); Pong3(){ start();

Multithreading mediante implementazione Runnable 1 import java.io.*; public class PingPong{ //il main crea e lancia i thread public static void main(string[] a){ Ping c=new Ping(); Pong t=new Pong(); Thread th1=new Thread(c); th1.start(); Thread th2=new Thread(t); th2.start(); class Ping implements Runnable{ try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); class Pong implements Runnable{ try{ Thread.sleep(990); catch (InterruptedException e){ System.out.println("\tPong");

Multithreading mediante implementazione Runnable 2 import java.io.*; public class PingPong1{ // file PingPong1.java public static void main(string[] a){ Ping1 c=new Ping1(); Pong1 t=new Pong1(); class Ping1 implements Runnable{ //file Ping1.java. Ogni oggetto crea e lancia il proprio thread Thread th; try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); Ping1() {th=new Thread(this); th.start(); class Pong1 implements Runnable{ //file Pong1.java Thread th; try{ Thread.sleep(990); catch (InterruptedException e){ System.out.println("\tPong"); Pong1(){ th=new Thread(this); th.start();

In ogni caso, l uscita è: $ java PingPong2 Ping Pong Ping Pong Ping Pong... Non ci sono differenze rilevanti tra le due implementazioni!

Alcuni metodi di Thread public void start() //lancia il thread public void run() //esegue il codice public final void stop() //distrugge il thread public final void suspend() //sospende il thread public final void resume() //riattiva il thread public static void sleep(long n) //sospende il thread per n ms public final void setpriority(int priority) //modifica la priorita public final int getpriority() //ottiene la priorità corrente public static void yield() //rischedula public final native boolean isalive() //esce con true se il //thread è vivo

Suspend/Stop/Resume import java.io.*; class Ping implements Runnable{ try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th1=new Thread(c); System.out.println("esegue"); th1.start(); System.out.println("sospende"); th1.suspend(); // fai qualcosa... Th1.resume();

Suspend/Stop/Resume import java.io.*; class Ping implements Runnable{ try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th1=new Thread(c); System.out.println("stop"); th1.start(); th1.stop(); System.out.println("il thread e' stato fermato"); th1.join();

Suspend/Stop/Resume import java.io.*; class Ping implements Runnable{ try{ Thread.sleep(800); catch(interruptedexception e) { System.out.println("Ping"); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th1=new Thread(c); System.out.println("stop"); th1.start(); th1.suspend(); th1.resume();

Stop/Suspend/Resume Attenzione: Stop() e suspend(): rischio di deadlock!! Supponiamo che il thread avesse acquisito una risorsa in mutua esclusione! Dal JDK 1.2 stop(), suspend() e resume() deprecated Usare wait() e notify()! La JVM associa ad ogni oggetto che chiama l'istruzione synchronized un LOCK. Funzione della wait(): - rilascia il LOCK wait() deve essere inserita in un metodo synchronized - inserisce il thread in coda d'attesa - mette il thread in stato NotRunnable Esempio: Public synchronized void Esempio(){ if(!condizione) try { wait(); catch(interruptedexception e) {System.out.println("eccezione di wait!");

Setpriority/getpriority import java.io.*; class Ping implements Runnable{ //ricava la Priorita' del thread System.out.println( th.getname()+" attuale "+th.getpriority()); //cambia la priorita' th.setpriority(thread.max_priority); //ricava la Priorita' del thread System.out.println(th.getName()+" nuova "+th.getpriority()); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th1=new Thread(c); System.out.println("esegue"); th1.start();

Yeld import java.io.*; class Ping implements Runnable{ if ((i % 10) == 0) { System.out.println(Thread.currentThread().getName() + " sta trasferendo il controllo..."); Thread.yield(); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th1=new Thread(c); th1.start(); Ping c = new Ping(); Thread th1=new Thread(c); th1.start();

isalive import java.io.*; class Ping implements Runnable{ Thread th = Thread.currentThread(); //Tests if this thread is alive System.out.println(th.isAlive()); public static void main(string[] a) throws Exception{ Ping c = new Ping(); Thread th=new Thread(c); th.start(); th.join(); System.out.println(th.isAlive());

Stati di un Thread new Thread() yield() New thread start() Runnable suspend() sleep() wait() resume() notify() Not Runnable stop() stop() run() exit stop() Dead

Passaggio di parametri tra Thread Mediante visibilità delle variabili (attribuzione public static) Possibile solo per piccoli programmi import java.io.*; public class PingPong2{ // il main crea e lancia i thread public static int numero=0; public static void main(string[] a){ Ping2 c=new Ping2(); c.start(); Pong2 t=new Pong2(); t.start(); class Ping2 extends Thread{ try{ Thread.sleep(800); catch(interruptedexception e) { PingPong2.numero++; System.out.println("Ping "+PingPong2.numero); class Pong2 extends Thread{ try{ Thread.sleep(990); catch (InterruptedException e){ PingPong2.numero++; System.out.println("\tPong " +PingPong2.numero);

Passaggio di parametri tra Thread Tutti i thread devono condividere un oggetto, che contiene i dati e i metodi La condivisione viene effettuata mediante definizione del puntatore all oggetto in ciascun thread, e mediante l inizializzazione del puntatore all oggetto L oggetto in realta viene allocato nella classe principale (quella che contiene il main) Esempio: due thread p1 e p2 che si scambiano 5 reali, con ritardo (genera sequenzialita quindi in questo caso non ci sono problemi di mutua esclusione) public class pth{ public static void main(string[] a){ z buf=new z(); p1 c=new p1(buf); p2 t=new p2(buf); c.start(); t.start(); Definizione della classe z: import java.io.*; public class z{ float b[]= new float[10]; void put(int i, float f){ b[i]=f; float get(int i){ return(float)b[i];

Passaggio di parametri tra Thread Scrittura delle classi p1.java e p2.java public class p1 extends Thread{ z buf; p1(z buf){ this.buf=buf; try{ Thread.sleep(800); catch(interruptedexception e) { System.out.print("leggo "); for (int i=0; i<5; i++) System.out.print( "+buf.get(i)); System.out.println(); public class p2 extends Thread{ z buf; Random r=new Random(); p2(z buf){ this.buf=buf; try{ Thread.sleep(990); catch (InterruptedException e){ System.out.print("\tscrivo "); for(int i=0; i<5; i++) { buf.put(i,r.nextfloat()); System.out.print(" "+buf.get(i)); System.out.println();

Passaggio di parametri tra Thread In questo esempio si usano dei thread in Java che si scambiano dei dati mediante una classe condivisa, Buffer. La sincronizzazione e realizzata mediante algoritmo che attende se i puntatori di in e out sono coincidente. Attenzione: questa soluzione funziona solo con 1 produttore e 1 consumatore! Se ho piu produttori o piu consumatori, devo usare la mutua esclusione! Classe condivisa: import java.io.*; public class Buffer{ private int buf[]= new int[10]; private int in, out; Buffer(){ in=0; out=0; int get_in(){ return in; int get_out(){ return out; void put_in(int a){ in=a; void put_out(int b){ out=b; void put(int i, int f){ buf[i]=f; int get(int i){ return (int)buf[i];

Passaggio di parametri tra Thread Produttore: public class Prod extends Thread{ // produttore Buffer buf; Random r; Prod(Buffer p){ this.buf=p; r=new Random(); int val; val=r.nextint(); while (buf.get_out()==((buf.get_in()+1)%10)); buf.put(buf.get_in(),val); System.out.println("\nproduco "+val+" in="+buf.get_in()); buf.put_in((buf.get_in()+1)%10); Consumatore public class Cons extends Thread{ // consumatore Buffer buf; Cons(Buffer p){ this.buf=p; int val; while (buf.get_out()==buf.get_in()); val=buf.get(buf.get_out()); System.out.println("\nconsumo "+val+" out="+buf.get_out()); buf.put_out((buf.get_out()+1)%10);

Passaggio di parametri tra Thread Altro consumatore public class Cons1 extends Thread{ // consumatore Buffer buf; Cons1(Buffer p){ this.buf=p; int val; while (buf.get_out()==buf.get_in()); val=buf.get(buf.get_out()); System.out.println("\ncons_1 "+val+ out="+buf.get_out()); buf.put_out((buf.get_out()+1)%10); Programma principale: public class pc{ public static void main(string[] a){ Buffer buf=new Buffer(); Prod c=new Prod(buf); Cons t=new Cons(buf); Cons1 z=new Cons1(buf); c.start(); t.start(); z.start();

Passaggio di parametri e sincronizzazione tra Thread Una soluzione al problema e quello di usare un arbitro software. In questo caso si usa l alternanza stretta. La classe condivisa e la seguente: import java.io.*; public class BufferPlus{ private int buf[]= new int[10]; private int in, out; private int blk; BufferPlus(){ in=0; out=0; blk=0; int get_in(){ return in; int get_out(){ return out; void put_in(int a){ in=a; void put_out(int b){ out=b; void put(int i, int f){ buf[i]=f; int get(int i){ return (int)buf[i]; int getblk(){ return (int)blk; void putblk(int a){blk=a;

Passaggio di parametri e sincronizzazione tra Thread Primo consumatore: import java.util.*; public class ConsPlus extends Thread{ // consumatore BufferPlus buf; ConsPlus(BufferPlus p){ this.buf=p; int val; while( buf.getblk() == 0); { while (buf.get_out()==buf.get_in()); val=buf.get(buf.get_out()); System.out.println("\nconsumo "+val+ out="+buf.get_out()); buf.put_out((buf.get_out()+1)%10); buf.putblk(0);

Passaggio di parametri e sincronizzazione tra Thread Secondo consumatore: import java.util.*; public class Cons1Plus extends Thread{ // consumatore BufferPlus buf; Cons1Plus(BufferPlus p){ this.buf=p; int val; while(buf.getblk()==1); { while (buf.get_out()==buf.get_in()); val=buf.get(buf.get_out()); System.out.println("\ncons_1 "+val+ out="+buf.get_out()); buf.put_out((buf.get_out()+1)%10); buf.putblk(1);

Monitors in Java La soluzione alla mutua esclusione in Java e data dall uso dei monitor (Hoare) I monitor sono realizzati mediante i metodi synchronized: il thread che esegue un metoro synchronized di un oggetto deve preventivamente acquisire il monito associato all oggetto Il monitor viene rilasciato all uscita dal metodo All interno di un metodo synchronized e possibile sospendere il thread che sta eseguendo attraverso l uso dello statement wait() Wait provoca la sospensione del thread ed il rilascio del monitor da lui posseduto I thread sospesi possono essere risvegliati usando i metodi notify() e notifyall() Questi metodi possono essere invocati solo all interno di metodi synchronized L effetto di notify() e notifyall() e la ripresa dell esecuzione dei thread sospesi sul monitor detenuto dal thread che esegue la notify o la notifyall

Esempio di monitor in Java Riconsideriamo l esempio del produttore/consumatore: Classe condivisa: import java.io.*; public class BufferMon { private int buf[]= new int[10]; private int in, out; BufferMon(){ in=0; out=0; synchronized void put(int f) { if( ((in+1)%10) == out) try{ wait(); catch(interruptedexception e){; buf[in]=f; System.out.println("produco "+f+" in="+in); in=(in+1)%10; notify(); synchronized int get() { if(out == in) try{ wait(); catch(interruptedexception e){; int val=buf[out]; System.out.print("get "+val+" out="+out); out=(out+1)%10; notify(); return(val);

Esempio di monitor in Java Consumatore import java.util.*; public class ConsMon extends Thread{ // consumatore BufferMon buf; ConsMon(BufferMon p){ this.buf=p; int val=buf.get(); System.out.println("cons = "+val); Altro consumatore import java.util.*; public class Cons1Mon extends Thread{ // consumatore BufferMon buf; Cons1Mon(BufferMon p){ this.buf=p; int val=buf.get(); System.out.println("cons_1 = "+val);

Esempio di monitor in Java Produttore: import java.util.*; public class ProdMon extends Thread{ // produttore BufferMon buf; Random r; ProdMon(BufferMon p){ this.buf=p; r=new Random(); buf.put(r.nextint()); Principale: public class pcmon{ public static void main(string[] a){ BufferMon buf=new BufferMon(); ProdMon c=new ProdMon(buf); ConsMon t=new ConsMon(buf); Cons1Mon z=new Cons1Mon(buf); c.start(); t.start(); z.start();