Introduzione al Corso, Thread Pooling - e-learning

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 ([email protected]),
 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