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



Похожие документы
SAPIENZA Università di Roma Facoltà di Ingegneria dell Informazione, Informatica e Statistica

GESTIONE DEI PROCESSI

Java Virtual Machine

Java threads (2) Programmazione Concorrente

Multithreading in Java. Fondamenti di Sistemi Informativi

Un esercizio d esame. Flavio De Paoli

Esercitazione n 4. Obiettivi

Telematica II 17. Esercitazione/Laboratorio 6

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:

Parcheggio.rtf 1/8 6 gennaio Prova di programmazione: parcheggio a pagamento

Algoritmi di Ricerca. Esempi di programmi Java

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

19. Introduzione al multi-threading

Ottava Esercitazione. introduzione ai thread java mutua esclusione

Programmazione concorrente in Java

Gruppi di Thread. Java threads (3) Gruppi di thread e Timer. Operating Systems. Operating Systems. Java threads 3. Java threads 3

Esercizi della lezione 5 di Java

Esercizi sul Monitor in Java

Prova d Esame Compito B

Programmazione Orientata agli Oggetti in Linguaggio Java

Prova d Esame Compito A

GESTIONE INFORMATICA DEI DATI AZIENDALI

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE

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

ELEMENTI DI PROGETTAZIONE SOFTWARE

13. Chain of Responsibility

Main System Monitor Keyboard

Esercizio Sincronizzazione Thread

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

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

Concetti Base Eccezioni Eccezioni e Metodi Gerarchia di Eccezioni. Java: Eccezioni. Damiano Macedonio

7 Esercitazione (svolta): Callback. Polling. Java RMI: callback. Server. Server. Client. Client. due possibilità:

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a settembre 2011

Gestione dei thread in Java LSO 2008

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

Corso di Laurea in Ingegneria Gestionale Esame di Informatica - a.a luglio 2013

Gestione delle Eccezioni

QUEUE : considerazioni. QUEUE : considerazioni. QUEUE : esempio. QUEUE : esempio

Il costrutto monitor [Hoare 74]

Realizzazione di una classe con un associazione

SAPIENZA Università di Roma, Facoltà di Ingegneria

Esercizi sulla definizione di classi (Fondamenti di Informatica 1 Walter Didimo) Soluzioni

Test di unità con JUnit4

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

Architettura Client-Server

Java: Compilatore e Interprete

appunti delle lezioni Architetture client/server: applicazioni server

RMI Remote Method Invocation

Lezione n.2 LPR - Informatica Applicata Thread Pooling, Callable Gestione Indirizzi IP

Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A Esercitazione. Programmazione Object Oriented in Java

FONDAMENTI di INFORMATICA L. Mezzalira

Programmazione a oggetti e JAVA. Prof. B.Buttarazzi A.A. 2011/2012

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Esercizi sugli Oggetti Monitor

Controllo degli accessi

Corso sul linguaggio Java

Concetto di Funzione e Procedura METODI in Java

Java:Struttura di Programma. Fabio Scanu a.s. 2014/2015

3. La sintassi di Java

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

Studente (Cognome Nome): Corso di Informatica Corso di Laurea in Ingegneria Gestionale a.a Secondo Compitino 21 Dicembre 2006

Reflection in Java. Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A

Synchronized (ancora)

INFORMATICA GRAFICA - FONDAMENTI DI INFORMATICA Ing. Civile - Edile/Architettura Dott. Penzo SOLUZIONE PROVA SCRITTA DEL 16/09/2002.

Il costrutto monitor [Hoare 74]

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

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

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).

Esempi di esercizi d esame

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

13 - Gestione della Memoria nella Programmazione Orientata agli Oggetti

Esercitazioni di Progettazione del Software. Esercitazione (Prova al calcolatore del 17 settembre 2010)

Corso sul linguaggio Java

Definizione di classi con array di oggetti

Corso di Reti di Calcolatori L-A

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

TFA 42 Sistemi e Reti di Calcolatori per la Didattica

Corso di Laurea in Ingegneria Gestionale Esame di Informatica a.a giugno 2013

Programmazione ad Oggetti Modulo A (Esame del 11/9/2015)

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

Esercitazione 6. Tutor: Ing. Diego Rughetti. Anno Accademico 2007/2008

Programmazione 1 A.A. 2015/2016

RMI. Java RMI RMI. G. Prencipe

Specifica i tipi di oggetti a creare, utilizzando un istanza prototipo, e crea nuove istanze tramite la copia di questo prototipo.

Scope e visibilità per classi

Programmazione in Java Parte I: Fondamenti

Monitor. Introduzione. Struttura di un TDA Monitor

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Esempio produttori consumatori. Primitive asincrone

Corso di Linguaggi di Programmazione

Транскрипт:

La concorrenza in Java package java.util.concurrent Antonio Furone Coda Bloccante La classe LinkedTransferQueue è stata esplicitamente disegnata per dare supporto a problemi di tipo produttore/consumatore. Il trasferimento di elementi tra produttore e consumatore può avvenire anche con la modalità bloccante, nella quale il produttore rimane in attesa durante il trasferimento di nuovo elemento nella coda (put) fino a quando il consumatore non ha effettivamente consumato il precedente elemento. Di seguito viene riportato l esempio di un Produttore che inserisce n elementi in una coda con modalità bloccante (metodo transfer) e un ulteriore elemento in modalità non bloccante (metodo trytransfer), quindi eseguito solo se il passaggio al consumatore può avvenire immediatamente o entro un timeout specificato. package it.af; import java.util.concurrent.linkedtransferqueue; import java.util.concurrent.transferqueue; import java.util.logging.logger; public class LinkedTransferQueueSample { private static final Logger LOGGER = Logger.getLogger(LinkedTransferQueueSample.class.getName()); private static final int NUM_ELEMENTS = 5; // classe Producer public static class Producer implements Runnable { TransferQueue<String> queue = null; public Producer(TransferQueue<String> transfer) { this.queue = transfer; for (int i = 0; i < NUM_ELEMENTS; i++) { LOGGER.info("Thread" + Thread.currentThread().getId()+" Prodotto: Elemento " + i); queue.transfer("elemento " + i); LOGGER.info("Exception:" +e.getmessage()); Thread.sleep(100); LOGGER.info("Ignore exception:" +e.getmessage()); LOGGER.info("Thread" + Thread.currentThread().getId()+" Modalita' non bloccata "); queue.trytransfer("non bloccato"); LOGGER.info("Thread" + Thread.currentThread().getId()+" Trasferito elemento con modalita' non bloccata!");

// classe Consumer public static class Consumer implements Runnable { TransferQueue<String> queue = null; public Consumer(TransferQueue<String> transfer) { this.queue = transfer; for (int ind = 0; ind < NUM_ELEMENTS+1; ind++) { String element = queue.take(); LOGGER.info("Thread"+ Thread.currentThread().getId()+" Consumato: "+ element); LOGGER.info("Exception:" +e.getmessage()); // main public static void main(string[] args) throws InterruptedException { TransferQueue<String> queue =new LinkedTransferQueue<String>(); Producer aproducer =new Producer(queue); Thread treadproducer =new Thread(aProducer); treadproducer.start(); try { Thread.sleep(1_000); // attesa 1 sec LOGGER.info("Exception:" + e.getmessage()); Consumer aconsumer = new Consumer(queue); Thread treadconsumer = new Thread(aConsumer); treadconsumer.start(); Sincronizzazione di Task La classe Phaser (fasatore) è stata introdotta per consentire la realizzazione di complessi algoritmi paralleli che richiedono, ai thread coinvolti, di sincronizzarsi in diversi punti. La registrazione dei partecipanti (tipicamente Thread) al Phaser, avviene dinamicamente attraverso i metodi register() e bulkregister(int). Simmetricamente, i partecipanti possono rimuovere la propria registrazione in qualsiasi momento utilizzando, ad esempio, il metodo arriveandderegister(), mentre il metodo arriveandawaitadvance() segnala l arrivo (completamento di una fase) al Phaser da parte di un partecipante e l attesa dell arrivo degli altri partecipanti per eventualmente procedere. Ogni istanza del Phaser ha associato un numero di fase (intero) che viene incrementato ogni qualvolta tutti i soggetti interessati hanno comunicato il loro arrivo al fasatore. La sincronizzazione, come è facile intuire, prevede due fasi: arrivo e attesa. L arrivo viene notificato dai partecipanti attraverso i metodi arrive() e arriveandderegister(), i quali restituisco il numero di fase attiva. Nel momento in cui arriva l ultimo dei partecipanti alla fase, viene eseguito il metodo overridable onadvace(int,int), nel quale è possibile innestare una qualche azione di preavanzamento. L attesa da parte dei task viene implementata attraverso il metodo

awaitadvance(int), il quale termina quando il Phaser avanza e dove il parametro passato è l identificativo della fase (quello restituito ad esempio dal metodo arrive()). Un Phaser può entrare anche in uno stato di terminazione (il metodo isterminated() restituisce true) e quando ciò avviene, tutti i metodi di sincronizzazione terminano sbloccando eventuali thread in attesa e segnalando questo evento attraverso la restituzione di valori negativi. Di seguito viene riportato un esempio di utilizzo della classe Phaser con un gruppo di Thread che si sincronizzano su tre fasi e una classe (Monitor) che consente di monitorare lo stato del Phaser. package it.af; import java.util.concurrent.phaser; import java.util.concurrent.threadlocalrandom; import java.util.logging.logger; public class PhaserSample { private static final Logger LOGGER = Logger.getLogger(PhaserSample.class.getName()); private static final int NUM_THREADS = 10; private static String getcurrentthreadid() { String threadid = Thread.currentThread().getId() + ""; if (Thread.currentThread().getId() < 10) {threadid = "0" + threadid; return threadid; private static void dump(phaser aphaser, String txt) { LOGGER.info(txt+"\t"+" Thread :" + getcurrentthreadid()+" Fase: " + aphaser.getphase() + " reg.:"+ aphaser.getregisteredparties() + " arrivati:"+aphaser.getarrivedparties() + " non arrivati:"+aphaser.getunarrivedparties()); // classe Monitor static class Monitor implements Runnable { private final Phaser aphaser; public Monitor(Phaser givenphaser) { aphaser = givenphaser; while ( (aphaser!= null) &&(!aphaser.isterminated()) ) { PhaserSample.dump(aPhaser,"Monitor Start..."); Thread.sleep(80); LOGGER.info("Ignore exception:" + e.getmessage()); LOGGER.info("...Monitor Shutdown"); // MonitorPhaser static class Task implements Runnable { private final Phaser aphaser; public Task(Phaser givenphaser) { aphaser = givenphaser; aphaser.register();

// run execphase("fase A"); execphase("fase B"); execphase("fase C"); int newarrivalphase =aphaser.arriveandderegister(); dump(aphaser,"task Deregister. returned:"+ newarrivalphase); private void execphase(string phasename) { boolean last = false; dosomework(); String txt = phasename+" completata!"; if (aphaser.getunarrivedparties() == 1) { txt =" Ultimo thread arrivato!"; last = true; dump(aphaser, phasename + txt); int arrivalphase = aphaser.arrive(); dump(aphaser,phasename + " Await to advance..."); aphaser.awaitadvance(arrivalphase); dump(aphaser,phasename + " Advance next phase."); if (last) LOGGER.info("------------------------------------ "); // execnextphase private void dosomework() { // end Task LOGGER.info("Working...\t"+" Thread :" + getcurrentthreadid()); Thread.sleep( ThreadLocalRandom.current().nextInt(10,400)); LOGGER.info("Exception:" + e.getmessage()); public static void main(string[] args) { Phaser phaser = new Phaser(); Monitor amonitorphaser =new Monitor(phaser); new Thread(aMonitorPhaser).start(); for (int i = 0; i < NUM_THREADS; i++) { Task atask = new Task(phaser); new Thread(aTask).start(); Fork Join Il framework fork join è probabilmente il più interessante introdotto nel package della concorrenza con Java SE 7. Le classi core di tale framework sono la ForkJoinPool e ForkJoinTask. In particolare, gli oggetti di tipo ForkJoinTask vengono eseguiti appena sottoposti ad un oggetto di tipo ForkJoinPool. Le modalità attraverso le quali un oggetto ForkJoinTask può essere sottoposto

ad un ForkJoinPool, sono le seguenti: asincrona (attraverso il metodo execute), bloccante (metodo invoke) e con l'ottenimento di un oggetto "future" a sua volta da sottomettere (metodo submit). Una volta avviato, l oggetto ForkJoinTask tipicamente avvia un insieme di attività asincrone utilizzando il metodo fork() (e quindi join()). Di seguito viene riportato un esempio di utilizzo di tale framework per l implementazione dell algoritmo di ordinamento QuickSort. Nel caso specifico, viene utilizzata la subclass RecursiveAction della ForkJoinTask e nel metodo compute invocati iterativamente gli step di sort sui due subsets di dati individuati da partition. package it.af; import java.util.arraylist; import java.util.list; import java.util.concurrent.forkjoinpool; import java.util.concurrent.recursiveaction; import java.util.logging.logger; public class QuickSort<T extends Comparable<T>> extends RecursiveAction { private static final long serialversionuid = 1L; private static final Logger LOGGER = Logger.getLogger(PhaserSample.class.getName()); private List<T> data; private int lindex; private int uindex; private long taskid; public QuickSort(List<T> data) { this.data = data; this.lindex = 0; this.uindex = data.size() - 1; this.taskid = System.nanoTime(); outputstat("new (first) "); protected QuickSort(List<T> data,int lindex,int uindex,long taskid) { this.lindex = lindex; this.uindex = uindex; this.data = data; this.taskid = taskid; outputstat("new "); private void outputstat(string operation) { String threadid = Thread.currentThread().getId()+""; if (Thread.currentThread().getId() < 10) { threadid = "0"+threadId; LOGGER.info( " task id:"+this.taskid+ " thread:"+threadid+" op:"+operation); private int partition(int pivotindex) { T pivotvalue = data.get(pivotindex); // middle element swap(pivotindex, uindex); int storeindex = lindex; for (int i=lindex; i < uindex; i++) { if (data.get(i).compareto(pivotvalue) < 0) { swap(i, storeindex); storeindex++; swap(storeindex, uindex);

return storeindex; private void swap(int i, int j) { if (i!= j) { T ivalue = data.get(i); data.set(i, data.get(j)); data.set(j, ivalue); protected void compute() { if (lindex < uindex) { outputstat("start..."); int pivotindex = lindex + ((uindex - lindex) / 2); pivotindex = partition(pivotindex); invokeall( new QuickSort<>(data, lindex,pivotindex-1, System.nanoTime()), new QuickSort<>(data, pivotindex+1,uindex, System.nanoTime())); outputstat("... End"); public static void main(string[] args) { int MAX_SIZE = 50; List<Integer> sourcedata = new ArrayList<>(MAX_SIZE); for (int i=0; i<max_size; i++) { int randomvalue = (int) (Math.random() * 100_000); sourcedata.add(randomvalue); LOGGER.info("in="+sourceData); QuickSort<Integer> quicksort =new QuickSort<>(sourceData); // Pool di 6 threads ForkJoinPool pool = new ForkJoinPool(6); pool.invoke(quicksort); LOGGER.info("out="+sourceData);