Università degli Studi di Pisa
Dipartimento di Informatica
Laboratorio di Reti
Lezione 1
JAVA Thread Programming:
Introduzione, ThreadPooling
27/09/2016
Laura Ricci
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 1
INFORMAZIONI UTILI
• Riferimenti
Laura Ricci (laura.ricci@unipi.it),
Damiano Di Francesco Maesa (supporto alla didattica)
• Orario del Corso:
martedì 9.00-11.00
: lezione aula C1
martedì 14.00-16.00 : laboratorio aula H
• Ricevimento: giovedì ore 15.00-18.00, nel mio studio, in qualsiasi momento
per e-mail
• Moodle https://elearning.di.unipi.it/moodle/, pagina del corso
pubblicazione contenuti
forum,chats...
assignments
test
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 2
INFORMAZIONI UTILI
• esperienze pratiche in laboratorio
obiettivo: verifica esercizi assegnati nelle lezioni teoriche
bonus per esame se si consegna l'esercizio entro 15 giorni dalla data di
assegnazione.
• modalità di esame:
l’esame finale di Reti Calcolatori e Laboratorio: progetto + prova scritta
+ orale. Il progetto deve essere consegnato almeno una settimana prima
della data della prova scritta.
si può accedere allo scritto se e solo se il progetto ha ricevuto una
valutazione sufficiente.
per accedere alla prova orale conclusiva è necessario ottenere una
valutazione sufficiente del progetto e superare la prova scritta.
orale modulo laboratorio di reti : discussione del progetto + domande
sugli tutti argomenti trattati nelle lezioni teoriche
il progetto verrà consegnato in all’inizio di dicembre e rimarrà valido fino
a settembre 2017.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 3
INFORMAZIONI UTILI
Prerequisiti:
• corso di Programmazione 2, conoscenza del linguaggio JAVA: in
particolare:
packages
gestione delle eccezioni
collezioni
generics
• modulo di reti: conoscenza TCP/IP
Linguaggio di programmazione di riferimento: JAVA 8
concorrenza: costrutti base, JAVA.UTIL.CONCURRENT
JAVA.NIO
collezioni
rete: JAVA.NET, JAVA.RMI
Ambiente di sviluppo di riferimento: Eclipse
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 4
INFORMAZIONI UTILI
• Materiale Didattico:
lucidi delle lezioni
per la parte relativa ai threads
Bruce Eckel – Thinking in JAVA – Volume 3 - Concorrenza e Interfacce
Grafiche
B. Goetz, JAVA Concurrency in Practice, 2006
Per la parte relativa alla programmazione di rete
Dario Maggiorini Introduzione alla Programmazione Client Server,
Pearson
Esmond Pitt Fundamental Networking in JAVA
• Materiale di Consultazione:
Harold, JAVA Network Programming 3nd edition O'Reilly 2004.
K.Calvert, M.Donhaoo, TCP/IP Sockets in JAVA, Practical Guide for
Programmers
Costrutti di base Horstmann ,Concetti di Informatica e Fondamenti di Java 2
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 5
PROGRAMMA PRELIMINARE DEL CORSO
Threads
creazione ed attivazione di threads, Callable: threads che restituiscono i
risultati, interruzioni
meccanismi di gestione di pools di threads
mutua esclusione, lock implicite ed esplicite
il concetto di monitor: sincronizzazione di threads su strutture dati
condivise: synchronized, wait, notify, notifyall
concurrent collections
Stream ed IO
Streams: tipi di streams, composizione di streams
meccanismi di serializzazione
serializzazione standard di JAVA: problemi
JSON
U
continua....
Dipartimento di Informatica
Università degli Studi di Pisa
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 6
PROGRAMMA PRELIMINARE DEL CORSO
Programmazione di rete a basso livello
●
connection oriented Sockets
●
connectionless sockets: UDP, multicast
HTTP e servizi web
Non blocking IO
Oggetti Distribuiti
definizione di oggetti remoti
il meccanismo di Remote Method Invocation in JAVA
dynamic code loading
problemi di sicurezza
il meccanismo delle callbacks
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 7
IL CAMMINO FINO A JAVA 8
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 8
IL CAMMINO FINO A JAVA 8
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 9
IN QUESTO CORSO: CLASSI IN BLU
• 1.0.2 prima versione stabile, rilasciata il 23 gennaio del 1996
AWT Abstract Window Tollkit, applet
Java.lang (supporto base per concorrenza), Java.io, Java.util
Java.net (socket TCP ed UDP, Indirizzi IP, ma non RMI)
• 1.1: RMI, Reflections,....
• 1.2: Swing (grafica), RMI-IIOP, …
• 1.4: regular expressions, assert, NIO, IPV6
• JAVA 5: una vera rivoluzione generics, concorrenza,....
• 7: acquisizione da parte di Oracle: framework fork and join
• 8: Lambda Expressions
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 10
CONCURRENT PROGRAMMING: MOTIVAZIONI
●
concurrent programming: una storia iniziata molti anni fa, recentemente
diventata un “hot topic”
●
legge di Moore (Gordon Moore, cofondatore di INTEL):
https://it.wikipedia.org/wiki/Legge_di_Moore
"the number of transistors that can be fit onto a square inch of
silicon doubles every 12 months with a reduction of the clock
speed"
●
“Multicore crisis”:
non aumento della frequenza di clock, ma riprogettazione dei processori per
contenere non uno ma più core sullo stesso chip
come distribuire il carico tra i diversi core?
nuovi linguaggi: Scala, Akka, nuove librerie di JAVA,GO,...
nuove metodologie di sviluppo del software
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 11
JAVA UTIL.CONCURRENCT FRAMEWORK
• JAVA < 5 built in for concurrency: lock implicite, wait, notify e poco più.
• JAVA.util.concurrency: lo scopo è lo stesso del framework
java.util.Collections: un toolkit general purpose per lo sviluppo di
applicazioni concorrenti.
no more “reinventing the wheel”!
• definire un insieme di utility che risultino:
standardizzate
facili da utilizzare e dacapire
high performance
utili in un grande insieme di applicazioni per un vasto insieme di
programmatori, da quelli più esperti a quelli meno esperti.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 12
JAVA UTIL.CONCURRENT FRAMEWORK
• sviluppato in parte da Doug Lea, disponibile ,come insieme di librerie JAVA
non standard prima della integrazione in JAVA 5.0.
• tra i package principali:
java.util.concurrent
• Executor, concurrent collections, semaphores,...
java.util.concurrent.atomic
• AtomicBoolean, AtomicInteger,...
java.util.concurrent.locks
• Condition
• Lock
• ReadWriteLock
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 13
JAVA 5 CONCURRENCT FRAMEWORK
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 14
THREAD: DEFINIZIONE
• Processo: programma in esecuzione
esempio: se mando in esecuzione due diverse applicazioni, ad esempio
MS Word, MS Access, vengono creati due processi
• Thread (light weight process: un flusso di esecuzione all’interno di un
processo
• multitasking, si può riferire a thread o processi
a livello di processo è controllato esclusivamente dal sistema
operativo
a livello di thread è controllato, almeno in parte, dal programmatore
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 15
PROCESSI E THREADS
Thread verso process multitasking:
i thread condividono lo stesso spazio degli indirizzi
meno costoso
il cambiamento di contesto tra thread
la comunicazione tra thread
wsecuzione dei thread:
single core: multiplexing, interleaving (meccanismi di time sharing,...)
multicore: più flussi in esecuzione eseguiti in parallelo, simultaneità di
esecuzione
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 16
MULTITHREADING: PERCHE’?
●
●
Struttura di un browser:
●
visualizza immagini sullo schermo
●
controlla input dalla keyboard e da mouse
●
invia e ricevi dati dalla rete
●
leggi e scrivi dati su un file
●
esegui computazione (editor, browser, game)
come gestire tutte queste funzionalità simultaneamente? una decomposizione
del programma in threads implica:
●
●
modularizzazione della struttura dell’applicazione
●
aumento della responsiveness
altre applicazioni complesse che richiedono la gestione contemporanea di più
attività ad esempio: applicazioni interattive distribuite come giochi
multiplayers
●
interazione con l'utente + messaggi da altri giocatori (dalla rete...)
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 17
MULTITHREADING: PERCHE’?
●
Cattura la struttura della applicazione
●
molte componenti interagenti
●
ogni componente gestita da un thread separato
●
semplifica la programmazione della applicazione
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 18
MULTITHREADING: PERCHE’?
●
struttura di un server sequenziale
●
ogni client deve aspettare la terminazione del servizio della richiesta
precedente
●
●
responsiveness limitata
struttura di un server multithreaded
●
un insieme di worker therad per ogni client
●
aumento responsiveness
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 19
MULTITHREADING: PERCHE’?
• Migliore utilizzazione delle risorse
quando un thread è sospeso, altri thread vengono mandati in esecuzione
riduzione del tempo complessivo di esecuzione
• Migliore performance per computationally intensive application
dividere l’applicazione in task ed eseguirli in parallelo
• Tanti vantaggi, ma anche alcuni problemi:
più difficile il debugging e la manutenzione del software rispetto ad un
programma single threaded
race conditions, sincronizzazioni
deadlock, livelock, starvation,...
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 20
CREAZIONE ED ATTIVAZIONE DI THREAD
• quando si manda in esecuzione un programma JAVA, la JVM crea un thread
che invoca il metodo main del programma:
almeno un thread per ogni programma
• altri thread sono attivati automaticamente da JAVA (gestore eventi,
interfaccia, garbage collector,...).
• ogni thread durante la sua esecuzione può creare ed attivare altri threads.
• come ogni cosa in JAVA, un thread è un oggetto. Come creare ed attivare un
thread?
definire un task, ovvero definire una classe C che implementi
l'interfaccia Runnable, creare una istanza di C, quindi creare un thread
passandogli l’istanza del task creato
estendere la classe java.lang.Thread
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 21
RUNNABLE INTERFACE
• appartiene al package java.language
contiene solo la segnatura del metodo void run()
• una classe C che implementa l'interfaccia deve fornire un'implementazione
del metodo run()
• un oggetto istanza di C è un task: un fragmento di codice che può essere
eseguito in un thread
la creazione del task non implica la creazione di un thread per lo
esegua.
lo stesso task può essere eseguito da più threads: un solo codice, più
esecutori
• un oggetto Thread viene istanziato con un riferimento al task da eseguire
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 22
ATTIVAZIONE DI THREADS: UN ESEMPIO
• Scrivere un programma che stampi le tabelline moltiplicative dall' 1 al 10
si attivino 10 threads
ogni numero n, 1 n 10, viene passato ad un thread diverso
il task assegnato ad ogni thread consiste nello stampare la tabellina
corrispondente al numero che gli è stato passato come parametro
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 23
IL TASK CALCULATOR
public class Calculator implements Runnable {
private int number;
public Calculator(int number) {
this.number=number }
public void run() {
for (int i=1; i<=10; i++){
System.out.printf("%s: %d * %d = %d\n",
Thread.currentThread().getName(),number,i,i*number);
}}}
• NOTA: public static native Thread currentThread ( ):
più thread potranno eseguire il codice di Calculator
qual'è il thread che sta eseguendo attualmente questo codice?
CurrentThread() restituisce un riferimento al thread che sta eseguendo il
segmento di codice all'interno del quale si trova la sua invocazione
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 24
IL MAIN PROGRAM
public class Main {
public static void main(String[] args) {
for (int i=1; i<=10; i++){
Calculator calculator=new Calculator(i);
Thread thread=new Thread(calculator);
thread.start();}
System.out.println("Avviato Calcolo Tabelline"); } }
L'Output Generato dipende dalla schedulazione effettuta, un esempio è il seguente:
Thread-0: 1 * 1 = 1
Thread-9: 10 * 1 = 10
Thread-5: 6 * 1 = 6
Thread-8: 9 * 1 = 9
Thread-7: 8 * 1 = 8
Thread-6: 7 * 1 = 7
Avviato Calcolo Tabelline
Thread-4: 5 * 1 = 5
Thread-2: 3 * 1 = 3
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 25
ALCUNE OSSERVAZIONI
●
Output generato (dipendere comunque dallo schedulatore):
Thread-0: 1 * 1 = 1
Thread-9: 10 * 1 = 10
Thread-5: 6 * 1 = 6
Thread-8: 9 * 1 = 9
Thread-7: 8 * 1 = 8
Thread-6: 7 * 1 = 7
Avviato Calcolo Tabelline
Thread-4: 5 * 1 = 5
Thread-2: 3 * 1 = 3
• da notare: il messaggio Avviato Calcolo Tabelline è stato visualizzato prima che
tutti i threads completino la loro esecuzione. Perchè?
il controllo ripassa al programma principale, dopo la attivazione dei threads
e prima della loro terminazione.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 26
METODO START( ) VERSO METODO RUN( )
public class Main {
public static void main(String[] args) {
for (int i=1; i<=10; i++){
Calculator calculator=new Calculator(i);
Thread thread=new Thread(calculator);
thread.run();}
System.out.println("Avviato Calcolo Tabelline"} }
Output generato
main: 1 * 1 = 1
main: 1 * 2 = 2
main: 1 * 3 = 3
…......
main: 2 * 1 = 2
main: 2 * 2 = 4
…......
Avviato Calcolo Tabelline
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 27
START E RUN
• non si crea un nuovo flusso di esecuzione (attivazione del thread) se:
si crea un oggetto istanza della classe Thread()
si invoca il metodo run() della classe che implementa l'interfaccia
Runnable
solo il metodo start() comporta la creazione di un nuovo thread()!
• cosa accade se sostituisco l'invocazione del metodo run alla start?
non viene attivato alcun thread
ogni metodo run() viene eseguito all'interno del flusso del thread
attivato per l'esecuzione del programma principale
flusso di esecuzione sequenziale
il messaggio “Avviato Calcolo Tabelline” viene visualizzato dopo
l'esecuzione di tutti i metodi metodo run() quando il controllo torna al
programma principale
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 28
ATTIVAZIONE DI THREADS: RIEPILOGO
Per definire tasks ed attivare threads che li eseguano
definire una classe R che implementi l' interfaccia Runnable, cioè
implementare il metodo run. In questo modo si definisce un oggetto
runnable, cioè un task che può essere eseguito
allocare un'istanza T di R
Per costruire il thread, utilizzare il costruttore
public Thread (Runnable target)
passando il task T come parametro
attivare il thread con una start() come nell'esempio precedente.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 29
ATTIVAZIONE DI THREADS
Il metodo start( )
• segnala allo schedulatore (tramite la JVM) che il thread può essere
attivato (invoca un metodo nativo). L'ambiente del thread viene
inizializzato
• rstituisce immediatamente il controllo al chiamante, senza attendere che il
thread attivato inizi la sua esecuzione.
NOTA: la stampa del messaggio “Avviato Calcolo Tabelline” precede
quelle effettuate dai threads. Questo significa che il controllo è stato
restituito al thread chiamante (il thread associato al main) prima che
sia iniziata l'esecuzione dei threads attivati
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 30
THREAD DEMONI
• i thread demoni sono thread che hanno il compito di fornire un servizio in
background fino a che il programma è in esecuzione, ma non sono intesi
come parte fondamentale del programma
•
quando tutti i thread non-demoni sono completati, il programma termina
(anche se si sono thread demoni in esecuzione)
• se ci sono thread non-demoni ancora in esecuzione, il programma non
termina
• un esempio di thread non-demone è il main()
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 31
THREAD DEMONI
public class SimpleDaemons implements Runnable {
public SimpleDaemons() { }
public void run() {
while(true) {
try { Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);}
System.out.println("termino"); }}
public static void main(String[] args) {
for(int i = 0; i < 10; i++){
SimpleDaemons sd=new SimpleDaemons();
Thread t= new Thread (sd);
t.setDaemon(true);
t.start();}
} }
Perchè non viene stampato alcun messaggio “termino”?
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 32
TERMINAZIONE DI PROGRAMMI CONCORRENTI
Per determinare la terminazione di un programma JAVA:
• un programma JAVA termina quando terminano tutti i threads non demoni
che lo compongono
• se il thread iniziale, cioè quello che esegue il metodo main( ) termina, i
restanti thread ancora attivi continuano la loro esecuzione, fino alla loro
terminazione.
• se uno dei thread usa l'istruzione
System.exit()
per terminare
l'esecuzione, allora tutti i threads terminano la loro esecuzione
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 33
IL CLASSE THREAD
La classe java.lang.Thread contiene metodi per:
• costruire un thread interagendo con il sistema operativo ospite
• attivare, sospendere, interrompere i threads
• non contiene i metodi per la sincronizzazione tra i thread. Questi metodi
sono definiti in java.lang.object, perchè la sincronizzazione opera su
oggetti
Costruttori:
• diversi costruttori che differiscono per i parametri utilizzati
nome del thread, gruppo a cui appartine il thread,...(.vedere le API)
Metodi
• possono essere utilizzati per interrompere, sospendere un thread,
attendere la terminazione di un thread + un insieme di metodi set e get
per impostare e reperire le caratteristiche di un thread
esempio: assegnare nomi e priorità ai thread
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 34
IL CLASSE THREAD
La classe java.lang.Thread contiene metodi per
• porre un thread allo stato blocked:
public static native void sleep (long M) sospende l'esecuzione
del thread, per M millisecondi.
durante l'intervallo di tempo relativo alla sleep, il thread può essere
interrotto
metodo statico: non può essere invocato su una istanza di un thread
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 35
GESTIRE LE INTERRUZIONI
• JAVA mette a disposizione un meccanismo per interrompere un thread e
diversi meccanismi per intercettare l'interruzione
dipendenti dallo stato in cui si trova un thread, running, blocked
il thread decide
interruzione
comunque
autonomamente
come
rispondere
alla
• un thread può essere interrotto e può intercettare l'interruzione in modi
diversi, a seconda dello stato in cui si trova
se
è sospeso l'interruzione
InterruptedException
causa
il
sollevamento
di
una
se è in esecuzione, può testare un flag che segnala se è stata inviata una
interruzione.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 36
GESTIONE DI INTERRUZIONI
Intercettare una interruzione quando il thread è sospeso
public class SleepInterrupt implements Runnable
{public void run ( ){
try{System.out.println("dormo per 20 secondi");
Thread.sleep(20000);
System.out.println ("svegliato");}
catch ( InterruptedException x )
{ System.out.println("interrotto");return;};
System.out.println("esco normalmente");}
}
se esiste un interrupt pendente al momento dell'esecuzione della sleep(),
viene sollevata immediatamenete una InterruptedException.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 37
GESTIONE DELLE INTERRUZIONI
public class SleepMain {
public static void main (String args [ ])
{
SleepInterrupt si = new SleepInterrupt();
Thread t = new Thread (si);
t.start ( );
try
{Thread.sleep(2000);}
catch (InterruptedException x) {
};
System.out.println("Interrompo l'altro thread");
t.interrupt(
);
System.out.println ("sto terminando..."); } }
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 38
INTERROMPERE UN THREAD
• implementazione del metodo interrupt(): imposta a true un valore booleano
nel descrittore del thread.
•
il flag vale true
se esistono interrupts pendenti
• è possibile testare il valore del flag mediante:
public static boolean Interrupted ( )
(metodo statico, si invoca con il nome della classe Thread.Interrupted( ))
public boolean isInterrupted ( )
deve essere invocato su un'istanza di un oggetto di tipo thread
entrambi i metodi
restituiscono un valore booleano che segnala se il thread ha ricevuto
un'interruzione
riportano il valore del flag a false
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 39
STATI DI UN THREAD
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 40
UN THREAD PER OGNI TASK: SVANTAGGI
Svantaggi della soluzione un thread per ogni task:
• thread Life Cycle Overhead
overhead per la creazione/distruzione dei threads che richiede una
interazione tra la JVM ed il sistema operativo
varia a seconda della piattaforma, ma non è mai trascurabile
per richieste di servizio frequenti e 'lightweight' può impattare
negativamente sulle prestazioni dell' applicazione
• resource consumption
molti threads idle quando il loro numero supera il numero di processori
disponibili. Alta occupazione di risorse (memoria,....)
sia il garbage collector che lo schedulatore sono 'sotto stress'
• stability limitazione al numero di threads imposto dalla JVM/dal SO
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 41
THREAD POOL: MOTIVAZIONI
•
un thread per ogni task risulta una soluzione improponibile, specialmente nel
caso di lightweight tasks molto frequenti.
•
esiste un limite oltre il quale non risulta conveniente creare ulteriori
threads
•
obiettivi:
definire un limite massimo per il numero di threads che possono essere
attivati concorrentemente in modo da;
sfruttare al meglio i processori disponibili
evitare di avere un numero troppo alto di threads in competizione
per le risorse disponibili
diminuire il costo per l'attivazione/terminazione dei threads
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 42
THREAD POOL: CONCETTI GENERALI
•
L'utente struttura l'applicazione mediante un insieme di tasks.
•
Task = segmento di codice che può essere eseguito da un esecutore.
in JAVA corrisponde ad un oggetto di tipo Runnable
•
Thread = esecutore di tasks.
•
Thread Pool
struttura dati la cui dimensione massima può essere prefissata, che
contiene riferimenti ad un insieme di threads
i thread del pool possono essere riutilizzati per l'esecuzione di più tasks
la sottomissione di un task al pool viene disaccoppiata dall'esecuzione del
thread. L'esecuzione del task può essere ritardata se non vi sono risorse
disponibili
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 43
THREAD POOL: CONCETTI GENERALI
•
L'utente
crea il pool e stabilisce una politica per la gestione dei thread del pool
che stabilisce
quando i thread del pool vengono attivati: (al momento della
creazione del pool, on demand, all'arrivo di un nuovo task,....)
se e quando è opportuno terminare l'esecuzione di un thread (ad
esempio se non c'è un numero sufficiente di tasks da eseguire)
sottomette i tasks per l'esecuzione al thread pool.
•
Il supporto, al momento della sottomissione del task, può
– utilizzare un thread attivato in precedenza, inattivo al momento
dell'arrivo del nuovo task
– creare un nuovo thread
– memorizzare il task in una struttura dati (coda), in attesa di eseguirlo
– respingere la richiesta di esecuzione del task
•
il numero di threads attivi nel pool può variare dinamicamente
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 44
THREADPOOL IN JAVA
•
implementazione del thread pooling:
– fino a J2SE 4 a carico del programmatore
– J2SE 5.0 definisce la libreria java.util.concurrent che contiene
metodi per
• creare un thread pool ed il gestore associato
• definire la struttura dati utilizzata per la memorizzazione dei
tasks in attesa
• definire specifiche politiche per la gestione del pool
•
il meccanismo introdotto permette una migliore strutturazione del codice
poichè tutta la gestione dei threads può essere delegata al supporto
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 45
THREADPOOL IN JAVA
●
alcune interfacce definiscono servizi generici di esecuzione
public interface Executor {
public void execute (Runnable task) }
public interface ExecutorService extends Executor
{.......... }
diversi servizi che implementano il generico ExecutorService
(ThreadPoolExecutor, ScheduledThreadPoolExecutor,..)
la classe Executors che opera come una Factory in grado di generare
oggetti di tipo ExecutorService con comportamenti predefiniti.
i tasks devono essere incapsulati in oggetti di tipo Runnable e passati
a questi esecutori, mediante invocazione del metodo execute()
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 46
SOTTOMISSIONE DI TASK AD UN SERVER
public class Main {
public static void main(String[] args) throws Exception
{
Server server=new Server();
for (int i=0; i<10; i++){
Task task=new Task("Task "+i);
server.executeTask(task);
}
server.endServer();}}
•
creazione di un server
•
sottomissione di una sequenza di task al server. Il server eseguirà i task
in modo concorrente utilizzando un thread pool.
•
terminazione del server
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 47
DEFINIZIONE DI UN SERVER CONCORRENTE
import java.util.concurrent.*;
public class Server {
private ThreadPoolExecutor executor;
public Server( )
{executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();}
public void executeTask(Task task){
System.out.printf("Server: A new task has arrived\n");
executor.execute(task);
System.out.printf("Server:Pool Size:%d\n",executor.getPoolSize());
System.out.printf("Server:Active Count:%d\n",executor.getActiveCount());
System.out.printf("Server:Completed Tasks:%d\n",executor.getCompletedTaskCount());
public void endServer() {
executor.shutdown();}}
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 48
NewCachedThreadPool
crea un pool con un comportamento predefinito:
•
se tutti i thread del pool sono occupati nell'esecuzione di altri task e c'è un
nuovo task da eseguire, viene creato un nuovo thread.
nessun limite sulla dimensione del pool
•
se disponibile, viene riutilizzato un thread che ha terminato l'esecuzione di
un task precedente.
•
se un thread rimane inutilizzato per 60 secondi, la sua esecuzione termina
●
Elasticità: “un pool che può espandersi all'infinito, ma si contrae quando la
domanda di esecuzione di task diminuisce”
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 49
UN TASK CHE SIMULA UN SERVIZIO...
•
in questo e nei successivi esempi, il singolo servizio sarà simulato inserendo delle
attese casuali (Thread.sleep( )), per semplicità
import java.util.*;
public class Task implements Runnable {
private String name;
public Task(String name){
this.name=name;
}
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 50
UN TASK CHE SIMULA UN SERVIZIO...
import java.util.*;
public class Task implements Runnable {
private String name;
public Task(String name){ this.name=name;}
public void run() {
System.out.printf("%s: Task %s \n",
Thread.currentThread().getName(),name);
try{
Long duration=(long)(Math.random()*10);
System.out.printf("%s: Task %s: Doing a task during %d seconds\n",
Thread.currentThread().getName(),name,duration);
Thread.sleep(duration);
}
catch (InterruptedException e) {e.printStackTrace();}
System.out.printf("%s: Task Finished %s \n",
Thread.currentThread().getName(),name);}}}
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 51
OSSERVARE L'OUTPUT: IL RIUSO DEI THREAD
Server: A new task has arrived
Server: Pool Size: 1
pool-1-thread-1: Task Task 0
Server: Active Count: 1
Server: Completed Tasks: 0
pool-1-thread-1: Task Task 0: Doing a task during 1 seconds
Server: A new task has arrived
Server: Pool Size: 2
Server: Active Count: 1
pool-1-thread-1: Task Finished Task 0
pool-1-thread-2: Task Task 1
pool-1-thread-2: Task Task 1: Doing a task during 7 seconds
Server: Completed Tasks: 0
Server: A new task has arrived
Server: Pool Size: 2
pool-1-thread-1: Task Task 2
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 52
AUMENTARE IL RIUSO
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception{
Server server=new Server();
for (int i=0; i<10; i++){
Task task=new Task("Task "+i);
server.executeTask(task);
Thread.sleep(5000);
}
server.endServer();}}
La sottomissione di tasks al pool viene distanziata di 5 secondi. In questo modo
l'esecuzione precedente è terminata ed il programma riutilizza dempre lo stesso
thread.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 53
AUMENTARE IL RIUSO
Server: A new task has arrived
Server: Pool Size: 1
pool-1-thread-1: Task Task 0
Server: Active Count: 1
Server: Completed Tasks: 0
pool-1-thread-1: Task Task 0: Doing a task during 6 seconds
pool-1-thread-1: Task Finished Task 0
Server: A new task has arrived
Server: Pool Size: 1
pool-1-thread-1: Task Task 1
Server: Active Count: 1
pool-1-thread-1: Task Task 1: Doing a task during 2 seconds
Server: Completed Tasks: 1
pool-1-thread-1: Task Finished Task 1
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 54
AUMENTARE IL RIUSO
Server: A new task has arrived
Server: A new task has arrived
Server: Pool Size: 1
pool-1-thread-1: Task Task 2
Server: Active Count: 1
pool-1-thread-1: Task Task 2: Doing a task during 5 seconds
Server: Completed Tasks: 2
pool-1-thread-1: Task Finished Task 2
Server: A new task has arrived
Server: Pool Size: 1
Server: Active Count: 1
pool-1-thread-1: Task Task 3
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 55
newFixedThreadPool( )
import java.util.concurrent.*;
public class Server {
private ThreadPoolExecutor executor;
public Server(){
executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(2);
}
…...
newFixedThreadPool(int N) crea un pool in cui:
●
●
vengono creati N thread, al momento della inizializzazione del pool, riutilizzati
per l'esecuzione di più tasks
quando viene sottomesso un task T
se tutti i threads sono occupati nell'esecuzione di altri tasks,T viene
inserito in una coda, gestita automaticamente dall'ExecutorService
la coda è illimitata
se almeno un thread è inattivo, viene utilizzato quel thread
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 56
CREAZIONE/ATTIVAZIONE THREADS: METODO 2
●
utilizzare funzionalità dei linguaggi ad oggetti: subclassing, overriding
●
creare una classe C che estenda la classe Thread ed effettuare l'
overriding del metodo run() definito di quella classe
●
●
istanziare un oggetto di quella classe: questo oggetto è un thread il cui
comportamento è quello definito nel metodo run su cui è stato fatto
l'overriding
invocare il metodo start() sull'oggetto istanziato.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 57
CREAZIONE/ATTIVAZIONE THREADS: METODO 2
public class Calculator extends Thread {
........
public void run() {
for (int i=1; i<=10; i++)
{System.out.printf("%s: %d * %d = %d\n",
Thread.currentThread().getName(),number,i,i*number);}}}
public class Main {
public static void main(String[] args) {
for (int i=1; i<=10; i++){
Calculator calculator=new Calculator(i);
calculator.start();}
System.out.println("Avviato Calcolo Tabelline"); } }
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 58
INTERAZIONE TRA THREADS: BLOCKING QUEUE
BlockingQueue (java.util.concurrent package): una coda “thread safe”
per quanto riguarda gli inserimenti e le rimozioni
• il produttore può inserire elementi nella coda fino a che la dimensione
della coda non raggiunge un limite, dopo di che si blocca e rimane
bloccato fino a che un consumatore non rimuove un elemento
• il consumatore può rimuovere elementi dalla coda, ma se tenta di
eliminare un elemento dalla coda, si blocca fino a che il produttore
inserisce un elemento nella coda.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 59
BLOCKINGQUEUE METHODS AND IMPLEMENTATIONS
• 4 metodi differenti, rispettivamente, per inserire, rimuovere, esaminare
un elemento della coda, ogni metodo ha un comportamento diverso
relativamente al caso in cui l'operazione non possa essere svolta
• BlockingQueue è un'interfaccia, alcune implementazioni disponibili:
– ArrayBlockingQueue
– DelayQueue
– LinkedBlockingQueue
– PriorityBlockingQueue
– SynchronousQueue
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 60
CODE THREAD SAFE: BLOCKINGQUEUE
import java.util.concurrent.*;
public class BlockingQueueExample {
public static void main(String[] args) throws Exception {
BlockingQueue queue = new ArrayBlockingQueue(1024);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
new Thread(producer).start();
new Thread(consumer).start();
Thread.sleep(4000);
}
}
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 61
CODE THREAD SAFE: BLOCKINGQUEUE
import java.util.concurrent.*;
public class Producer extends Thread{
protected BlockingQueue queue = null;
public Producer(BlockingQueue queue) {
this.queue = queue; }
public void run() {
try {
queue.put("1");
Thread.sleep(1000);
queue.put("2");
Thread.sleep(1000);
queue.put("3");
} catch (InterruptedException e) {
e.printStackTrace(); } } }
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 62
CODE THREAD SAFE: BLOCKINGQUEUE
import java.util.concurrent.*;
public class Consumer extends Thread {
protected BlockingQueue queue = null;
public Consumer(BlockingQueue queue) {
this.queue = queue; }
public void run() {
try {
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 63
BLOCKINGQUEUE IMPLEMENTATIONS
•
ArrayBlockingQueue è una coda di dimensione limitata, che memorizza gli
elementi all'interno di un array. Upper bound definito a tempo di
inizializazzione
•
LinkedBlockingQueue mantiene gli elementi in una struttura linkata che
può avere un upper bound, oppure, se non si specifica un upper bound,
l'upper bound è Integer.MAX_VALUE.
•
SynchronousQueue
non possiede capacità interna. Operazione di
inserzione deve attendere per una corrispondente rimozione e viceversa
(un pò fuorviante chiamarla coda).
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 64
ASSIGNMENT 1: CALCOLO DI
Scrivere un programma che attiva un thread T che effettua il calcolo
approssimato di Il programma principale riceve in input da linea di comando
un parametro che indica il grado di accuratezza (accuracy) per il calcolo di
ed il tempo massimo di attesa dopo cui il programma principale interomp
thread T.
Il thread T effettua un ciclo infinito per il calcolo di usando la serie di
Gregory-Leibniz ( = 4/1 – 4/3 + 4/5 - 4/7 + 4/9 - 4/11 ...).
Il thread esce dal ciclo quando una delle due condizioni seguenti risulta
verificata:
1) il thread è stato interrotto
2) la differenza tra il valore stimato di ed il valore Math.PI (della libreria
JAVA) è minore di accuracy
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 65
ASSIGNMENT 2: SIMULAZIONE UFFICIO POSTALE
•
Si vuole simulare il flusso di clienti in un ufficio postale che ha 4 sportelli.
Nell'ufficio esiste:
– un'ampia sala d'attesa in cui ogni persona può entrare liberamente.
Quando entra, ogni persona prende il numero dalla numeratrice e aspetta
il proprio turno in questa sala.
– una seconda sala, meno ampia, posta davanti agli sportelli, in cui si può
entrare solo a gruppi di k persone
•
Una persona si mette quindi prima in coda nella prima sala, poi passa nella
seconda sala.
•
Ogni persona impiega un tempo differente per la propria operazione allo
sportello. Una volta terminata l'operazione, la persona esce dall'ufficio
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 66
ASSIGNMENT 2: SIMULAZIONE UFFICIO POSTALE
•
Scrivere un programma in cui:
– l'ufficio viene modellato come una classe JAVA, in cui viene attivato un
ThreadPool di dimensione uguale al numero degli sportelli
– la coda delle persone presenti
esplicitamente dal programma
nella
sala
d'attesa
è
gestita
– la seconda coda (davanti agli sportelli) è quella gestita implicitamente dal
ThreadPool
– ogni persona viene modellata come un task, un task che deve essere
assegnato ad uno dei thread associati agli sportelli
– si preveda di far entrare tutte le persone nell'ufficio postale, all'inizio
del programma
•
Facoltativo: prevedere il caso di un flusso continuo di clienti e la possibilità
che l'operatore chiuda lo sportello stesso dopo che in un certo intervallo di
tempo non si presentano clienti al suo sportello.
U
Università degli Studi di Pisa
Dipartimento di Informatica
JAVA Threads:
Introduzione, Thread Pooling
Laura Ricci 67