Laboratorio di reti I: Il multithreading
Stefano Brocchi
[email protected]
22 ottobre, 2008
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
1 / 40
Il multithreading in Java
Uso della concorrenza
La concorrenza
Spesso è conveniente realizzare programmi che vengano eseguiti
concorrenzialmente
Questo può essere conveniente per vari motivi:
Allocare solo una piccola parte del programma alla gestione di una
determinata risorsa o di un evento specifico (come nel caso di
interfacce interattive)
Distribuire efficientemente il carico di lavoro fra le risorse (come nel
caso di multiprocessori o sistemi distribuiti)
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
2 / 40
Il multithreading in Java
Uso della concorrenza
I thread
La concorrenza può essere realizzata sia tramite l’uso di molteplici
processi o più thread (lightweight processes)
Dato che i thread fanno parte di un unico processo che li contiene, il
loro uso offre molti vantaggio rispetto alla gestione di più processi:
Creazione, avvio e context switch molto più rapidi
Occupazione di minori risorse (i thread condividono un’unica tabella di
processo)
Più semplice coordinazione e condivisione dei dati grazie allo spazio di
indirizzi comune
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
3 / 40
Il multithreading in Java
Il multithreading in Java
I thread in Java
Java fa uso del multithreading per la realizzazione della concorrenza
Esistenza di primitive per la gestione della sincronizzazione
Lo scheduling dei thread avviene tramite condivisione del tempo di
CPU (round robin) a priorità
Si ha l’impressione che tutti i thread vengano eseguiti
contemporaneamente
Un thread è rappresentato dalla classe Thread o dalle sue derivate
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
4 / 40
Il multithreading in Java
Il multithreading in Java
La classe Thread
Un oggetto Thread si può creare tramite vari costruttori tra cui:
public Thread()
Costruttore vuoto
public Thread(Runnable target)
Costruttore che richiede un oggetto di tipo runnable; questa è
un’interfaccia con il solo metodo public void run(). Vedremo come
con questo costruttore si specifica che il codice da eseguire
concorrentemente è nell’oggetto target
Esistono costruttori che permettono di specificare un nome del
thread. Se questo non viene specificato la JVM ne genererà uno
automaticamente
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
5 / 40
Il multithreading in Java
Il multithreading in Java
I metodi start e run
I metodi fondamentali per l’avvio concorrenziale di un thread sono
public void start() e public void run()
Il metodo start esegue il metodo run del thread concorrentemente al
thread corrente; può essere eseguito al più una volta per ogni thread
Il metodo run deve essere riscritto nelle classi che estendono Thread;
il metodo run di Thread richiama il run dell’oggetto di tipo
Runnable passato alla creazione, se disponibile
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
6 / 40
Il multithreading in Java
Il multithreading in Java
Realizzare il multithreading
Come si possono quindi sfruttare le funzionalità della classe Thread
per realizzare la concorrenza ? Due possibili metodi
Estendere la classe Thread; riscrivere il metodo run specificando cosı̀
il codice da eseguire concorrentemente
Implementare l’interfaccia runnable scrivendo un metodo run che
specifichi il codice da eseguire concorrentemente; utilizzare un
oggetto di tipo Thread per avviare l’esecuzione parallela
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
7 / 40
Il multithreading in Java
Il multithreading in Java
Realizzare il multithreading
Vediamo un esempio di multithreading estendendo Thread
public class myThread extends Thread {
public void run() {
// Altro codice
(1)
}
public static void main(String[] args) {
myThread mt = new myThread();
mt.start();
// Altro codice
(2)
}
}
Il codice nelle posizioni 1 e 2 verrà eseguito concorrentemente
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
8 / 40
Il multithreading in Java
Il multithreading in Java
Realizzare il multithreading
Vediamo invece un esempio di multithreading senza estendere Thread
public class myThread2 implements Runnable {
private Thread t = new Thread(this);
public void run() {
// Altro codice
(1)
}
public void start() {
t.start();
}
public static void main(String[] args) {
myThread2 mt = new myThread2();
mt.start();
// Altro codice
(2)
}
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
9 / 40
Il multithreading in Java
Il multithreading in Java
Realizzare il multithreading
Non estendere Thread può essere necessario quando la classe ha già
una classe padre
Notare che nel precedente codice i metodi di Thread non possono
essere utilizzati per il controllo del thread realizzato
Soluzioni: riscrivere i metodi necessari ed inoltrarli all’oggetto thread
utilizzato (nell’esempio t) oppure rendere possibile l’accesso a tale
thread (es. con un metodo getThread)
Solitamente estendendo Thread la realizzazione risulta un po’ più
semplice
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
10 / 40
Il multithreading in Java
Il multithreading in Java
Metodi di Thread
Altri metodi della classe Thread sono:
public static void sleep(long millis)
Mette il thread corrente in attesa per millis millisecondi; genera
un’InterruptedException se nel frattempo il thread viene interrotto
public void interrupt()
Se il thread è in attesa (per esempio per causa di un’istruzione sleep),
lo interrompe; altrimenti imposta nel thread un flag che segnali lo
stato di interruzione
public boolean isInterrupted()
Ritorna true se lo stato del thread è interrotto
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
11 / 40
Il multithreading in Java
Il multithreading in Java
Metodi di Thread
static void join()
Mette il thread corrente in attesa per la terminazione del thread su cui
viene chiamato il metodo; può generare una InterruptedException
public boolean isAlive()
Ritorna true se il thread è attualmente in esecuzione
public void setPriority(int newpriority)
Imposta la priorità del thread a newpriority (valori maggiori
indicano maggiore priorità)
public String getName()
Ritorna il nome associato al thread
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
12 / 40
Il multithreading in Java
Il multithreading in Java
Esempio di thread
Supponiamo di voler avviare due thread che eseguano delle operazioni
in parallelo
I due thread si dovranno arrestare quando l’utente preme un qualsiasi
tasto della tastiera
Realizziamo i thread estendendo la classe Thread
public class myThread extends Thread
Creiamo un metodo per imporre la terminazione ed un flag per
tenerne conto:
private boolean requestStop = false;
public void arresta() {
requestStop = true;
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
13 / 40
Il multithreading in Java
Il multithreading in Java
Esempio di thread
Nel metodo run implementiamo il codice che un singolo thread deve
eseguire:
public void run() {
System.out.println(getName() + " attivato");
while (! requestStop) {
// Operazioni da eseguire
}
System.out.println(getName() + " terminato");
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
14 / 40
Il multithreading in Java
Il multithreading in Java
Esempio di thread
A questo punto il codice che li richiama dovrà avviare i due thread ed
arrestarli dopo la ricezione di qualsiasi byte da standard input:
public static void main(String[] args)
throws IOException {
myThread mt = new myThread();
myThread mt2 = new myThread();
mt.start();
mt2.start();
System.in.read();
mt.arresta();
mt2.arresta();
System.out.println("Thread principale terminato ");
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
15 / 40
Il multithreading in Java
Il multithreading in Java
Esempio di thread
A volte per imporre la terminazione di un thread è necessario inoltre
richiamare una interrupt(): il thread potrebbe essere fermo su
un’istruzione sleep() o wait()
Il seguente Thread per esempio attende 10 secondi e stampa un
messaggio, oppure segnala se viene interrotto prima:
public void run() {
try {
Thread.sleep(10000);
System.out.println(getName() + ": passati 10 s.");
} catch (InterruptedException e) {
System.out.println(getName() + ": interrotto");
}
}
public void arresta() {
interrupt();
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
16 / 40
Il multithreading in Java
Il multithreading in Java
Thread demoni
In Java è possibile definire dei thread demoni che terminino
automaticamente quando tutti i thread non demoni hanno finito la
loro esecuzione
I thread demoni sono utili quando si ha necessità di un servizio
sempre attivo che però non ha senso di continuare se gli altri thread
terminano
Per esempio un thread che cattura l’input (detto anche listener) di
un’interfaccia grafica
Un thread può essere dichiarato demone o meno tramite una chiamata
al metodo setDaemon(boolean d) prima della partenza del thread.
Il metodo isDaemon() serve per sapere se un thread è demone
Thread avviati da thread demoni sono per default demoni
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
17 / 40
Il multithreading in Java
Esercizio
Esercizio
Creare una classe che stia in ascolto di input da tastiera ed alla
pressione dei tasti 1, 2 o 3 crei ed esegua un thread orologio
Un thread orologio stampa su schermo un messaggio del tipo
’Thread-n: avviato da tot secondi’ ogni 1, 2 o 3 secondi a
seconda del tasto premuto per il suo avvio
Al momento della pressione del tasto ’k’ (kill) un thread orologio deve
essere terminato immediatamente; deve essere stampato un
messaggio contenente il suo tempo di esecuzione del tipo ’Thread-n
terminato a tot ms dall’avvio’
Con la pressione del tasto ’q’ (quit) tutti i thread devono terminare
dopo la stampa del messaggio temporale successivo
Usare System.currentTimeMillis() per ottenere l’ora corrente
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
18 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Problematiche della concorrenza
L’ordine di esecuzione dei thread dipende da molteplici fattori non
prevedibili al momento della programmazione
Questo non determinismo può dar luogo a diverse problematiche in
quanto l’esecuzione con dati in input uguali può dar luogo a risultati
diversi
E’ necessario sincronizzare l’accesso alle risorse condivise per evitare
situazioni di incoerenza dei dati
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
19 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Problematiche della concorrenza: esempio
Consideriamo ad esempio un sistema di prenotazione di posti in un
cinema
Rappresentiamo il cinema con un oggetto Cinema contenente un
vettore di booleani posti che segnala se un posto è occupato
Consideriamo un metodo per la prenotazione prenota che specifica
in un vettore i posti da prenotare
Il metodo prenota può essere richiamato concorrentemente da più
thread rappresentanti le diverse interfacce di prenotazione
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
20 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Problematiche della concorrenza: esempio
Consideriamo la seguente implementazione di prenota
public void prenota(int[] p) {
for (int i = 0; i < p.length; i++) {
if (! posti[p[i]]) {
posti[p[i]] = true;
} else {
// Errore !
}
}
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
21 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Problematiche della concorrenza: esempio
Consideriamo che i due thread Thread1 e Thread2 cerchino di
prenotare il posto 100 inizialmente libero
Un possibile interlacciamento delle istruzioni potrebbe essere:
Thread1:
if (!
posti[100])
Thread2:
if (!
posti[100])
Thread2:
posti[100] = true;
Thread1:
posti[100] = true;
Cosı̀ facendo lo stesso posto rimarrebbe prenotato per due persone
diverse !
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
22 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Sincronizzazione
E’ necessario che alcuni metodi vengano eseguiti da un solo thread
alla volta
In Java questo si realizza con la parola chiave synchronized; un
metodo può essere dichiarato synchronized aggiungendo questa
parola chiave alla firma del metodo
Di tutti i metodi dichiarati synchronized di un oggetto, soltanto
uno alla volta può essere in esecuzione
Nell’esempio il problema della condivisione di risorse può essere risolto
dichiarando prenota come synchronized:
public void synchronized prenota(int[] p)
Se più metodi accedono a risorse condivise sarà necessario dichiararli
tutti synchronized se si vuole garantire la mutua esclusione
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
23 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
La parola chiave synchronized
In Java ogni oggetto possiede un campo lock che può essere
assegnato ad un solo thread alla volta
Quando un metodo synchronized entra in esecuzione il thread
corrente prende possesso del lock dell’oggetto
Un altro thread che cerca di eseguire un metodo sincronizzato sullo
stesso oggetto viene fermato e rimane in attesa del lock
Il lock viene rilasciato alla terminazione del metodo synchronized
Metodi synchronized possono essere riscritti non synchronized e
viceversa
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
24 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
La parola chiave synchronized
Si possono sincronizzare, invece di interi metodi, anche solo dei
blocchi di codice; la sincronizzazione può avvenire inoltre su di un
qualsiasi oggetto
public void metodo(int[] array) {
synchronized(array) {
// Esegui codice sincronizzato
}
// Esegui codice non sincronizzato
}
Visto che il codice sincronizzato può mettere in attesa un altro thread
è bene sincronizzare solo le parti che effettivamente necessitano di
mutua esclusione
Lo svantaggio di usare sincronizzazione in metodi non synchronized
è che questo non compare nella firma del metodo e deve essere quindi
documentato in altro modo
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
25 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Blocchi synchronized: esempio
Riconsideriamo l’esempio della prenotazione del cinema; desideriamo
realizzare un metodo prenota che prenoti dei posti tutti nella stessa
fila, e che quindi richieda l’accesso esclusivo soltanto a quella parte
della matrice
Questo si può ottenere creando un oggetto per ogni fila del cinema e
richiedendo il lock solo su quella fila
Utilizziamo un vettore di oggetti per rappresentare le file. Possiamo
utilizzare il tipo Object visto che l’unica cosa che ci interessa è l’uso
del lock
Consideriamo un metodo fila che dato un vettore di posti restituisca
l’oggetto corrisponde alla loro fila (e eventualmente lanci un’eccezione
se i posti sono su più file)
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
26 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Blocchi synchronized: esempio
L’implementazione potrebbe quindi essere la seguente
public class Cinema {
// Costruttore e campo posti omessi
private Object[] file;
private Object fila(int[] p) { ... }
public void prenota(int[] p) {
Object f = fila(p);
synchronized(f) {
for (int i = 0; i < p.length; i++) {
if (! posti[p[i]]) {
posti[p[i]] = true;
} else { /* Errore ! */ }
}
}
}
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
27 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Importanza della sincronizzazione
Durante l’accesso a risorse condivise la sincronizzazione è importante
anche per operazioni molto semplici, in quanto anche una singola
istruzione ad alto livello dovrà essere scomposta in più istruzioni
macchina per essere eseguita
Consideriamo un metodo con un’unica istruzione per l’incremento di
un contatore di una unità:
count = count + 1;
In linguaggio macchina questa istruzione verrà realizzata con una
procedura come la seguente:
1. Carica count in un registro
2. Incrementa il registro
3. Salva il registro come count
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
28 / 40
Il multithreading in Java
Problematiche della concorrenza e sincronizzazione
Importanza della sincronizzazione
Se il metodo viene eseguito concorrentemente da due thread si
possono generare situazioni di errore
Consideriamo la seguente possibile situazione di esecuzione,
considerando due thread T1 e T2 ed un valore iniziale per count di 3
1.
2.
3.
4.
5.
6.
T1:
T2:
T2:
T2:
T1:
T1:
Carica count in un registro (registro di T1 = 3)
Carica count in un registro (registro di T2 = 3)
Incrementa il registro (registro di T2 = 4)
Salva il registro come count (count = 4)
Incrementa il registro (registro di T1 = 4)
Salva il registro come count (count = 4)
Dopo due esecuzioni del metodo di incremento count è salito solo di
un’unità !
Per questo la sincronizzazione è pressochè sempre necessaria per la
modifica di risorse condivise
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
29 / 40
Il multithreading in Java
Coordinazione tra processi: uso di wait e notify
Altri tipi di sincronizzazione
Tramite il codice sincronizzato su di un oggetto si può imporre ad un
thread di stare in attesa se un altro ha un lock sullo stesso oggetto
Spesso può essere necessario mettere in attesa un processo anche in
base a condizioni più complesse
Consideriamo il problema del produttore e consumatore con buffer
limitato; se il buffer si riempie il produttore dovrà aspettare che almeno
un oggetto venga consumato prima di produrne un altro
In Java questo si può ottenere tramite i metodi di Object wait e
notify
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
30 / 40
Il multithreading in Java
Coordinazione tra processi: uso di wait e notify
Il metodo wait
Il metodo wait può essere richiamato solo su oggetti sul quale si è
sincronizzati, altrimenti si ottiene una
IllegalMonitorStateException
synchronized(o) {
o.wait();
// OK
}
o.wait();
// Generazione di un’eccezione
L’istruzione wait su di un oggetto o esegue le seguenti operazioni:
1. Rilascia il lock di o
2. Mette in attesa il thread corrente finchè non viene eseguita una notify
o notifyAll su o
3. Attende che il lock sia nuovamente disponibile
4. Occupa il lock su o e procede con l’esecuzione
Esiste anche una versione temporizzata della wait che attende al più
un dato tempo
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
31 / 40
Il multithreading in Java
Coordinazione tra processi: uso di wait e notify
Il metodo notify
Come per il metodo wait il metodo notify può essere richiamato
solo su oggetti sul quale si è sincronizzati
Il metodo notify sblocca un processo in wait sull’oggetto in
questione. Prima che il processo possa partire sarà anche necessario
che venga rilasciato il lock
E’ necessario accertarsi che per ogni thread che esegue una wait ce
ne sarà un altro che eseguirà sicuramente una notify altrimenti il
thread resterà in attesa indefinitamente
Gestire con attenzione anche le situazioni di terminazione anormale
come il lancio di un’eccezione
Il metodo notifyAll risveglia tutti i thread in attesa; tuttavia solo
uno potrà riottenere il lock mentre gli altri torneranno in wait.
Rispetto a notify questo metodo è più sicuro ma meno efficiente
Se non ci sono thread in attesa i metodi notify e notifyAll non
producono alcun effetto
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
32 / 40
Il multithreading in Java
Coordinazione tra processi: uso di wait e notify
Esempio: produttore e consumatore
Vediamo un possibile frammento di codice che implementa un
produttore di un paradigma produttore/consumatore con buffer
limitato:
synchronized(buffer) {
while (bufferFull()) {
buffer.wait();
}
produce();
buffer.notify();
}
Notare che l’istruzione wait è dentro un’istruzione while in quanto
non si può garantire che alla sua terminazione la condizione di
avanzamento (! bufferFull()) sia verificata
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
33 / 40
Il multithreading in Java
Coordinazione tra processi: uso di wait e notify
Esempio: produttore e consumatore
Del tutto simmetrico è il corrispondente frammento di codice nel
consumatore
synchronized(buffer) {
while (bufferEmpty()) {
buffer.wait();
}
consume();
buffer.notify();
}
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
34 / 40
Il multithreading in Java
Problematiche della concorrenza: deadlock
I deadlock
Può succedere che un gruppo di thread non possa procedere con
l’esecuzione in quanto ognuno di essi è in attesa di una risorsa
bloccata da un altro thread del gruppo
Un esempio:
Il thread 1 ha il lock su A ed è in attesa del lock di B
Il thread 2 ha il lock su B ed è in attesa del lock di A
In questi casi si parla di una situazione di deadlock
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
35 / 40
Il multithreading in Java
Problematiche della concorrenza: deadlock
I deadlock
Perchè ci sia un deadlock si devono verificare tutte le seguenti
condizioni
1. Almeno una risorsa deve essere accessibile da un solo thread alla volta
2. Almeno un thread può essere in attesa di una risorsa mentre ne ha
allocata un’altra
3. Una risorsa non può essere prelazionata ad un processo
4. Deve avvenire un’attesa circolare tra un gruppo di thread
Evitare che si verifichi anche una sola di queste condizioni vuol dire
evitare i deadlock
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
36 / 40
Il multithreading in Java
Problematiche della concorrenza: deadlock
Evitare i deadlock
Esistono varie strategie per evitare i deadlock
Implementare dei thread che richiedano contemporaneamente tutte le
risorse di cui necessitano per terminare; in questo modo un thread o
può essere eseguito fino in fondo o non occupa risorse mentre è in
attesa
Realizzare una tecnica per permettere ad un thread (magari di priorità
maggiore) di sottrarre risorse ad un altro
Per evitare l’attesa circolare solitamente occorre una progettazione ad
hoc a seconda del tipo di problema
In genere evitare i deadlock può essere comunque un problema
complesso
Evitare i deadlock non garantisce l’avanzamento di tutti i thread: può
succedere che un thread non avanzi perchè le risorse necessarie sono
sempre possedute da altri. In questo caso si parla di starvation
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
37 / 40
Il multithreading in Java
Esercizio (2)
Esercizio (2)
Realizzare una classe che, ricevendo in input da tastiera dei nomi di
file di testo, ne esegua delle copie con tutti i caratteri maiuscoli (vedi
esercizio sulle eccezioni)
Mentre il programma è in attesa di input i file già inseriti dovranno
essere processati
Saranno necessari un thread per l’input da tastiera, uno che esegue la
conversione ed un buffer condiviso a dimensione limitata che contiene
i nomi dei file ancora da processare
Se nell’input viene specificato il comando ’\quit’ il programma deve
smettere di richiedere dati in ingresso, aspettare la terminazione
dell’elaborazione sui file specificati e terminare
Il programma deve stampare su schermo informazioni riguardanti la
sua esecuzione come i file convertiti o eventuali situazioni di errore
(es. file not found); questi non devono venir visualizzati mentre
l’utente sta inserendo input ma tra un comando e l’altro
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
38 / 40
Il multithreading in Java
Esercizio (2)
Esercizio (2): testing
Per simulare il nondeterminismo tipico della concorrenza che per
programmi semplici come questo spesso non si percepisce, imporre
delle attese temporali casuali nei metodi che procedono con
l’elaborazione
Eseguire dei test con particolari dati in input per testare i casi che
potrebbero risultare in un errore (es. riempimento del buffer, file
inesistenti, verificarsi di errori di IO o altre eccezioni)
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
39 / 40
Il multithreading in Java
Esercizio (2)
Esercizio (2): funzioni aggiuntive
Progettare e pensare come potrebbero esser realizzate le seguenti
funzionalità:
Eseguire più thread contemporaneamente per l’elaborazione sui file
Possibilità di specificare con il comando ’\file nomefile’ di leggere dei
nomi di file da processare dal file specificato. La lettura da tale file
deve nuovamente avvenire in parallelo alla lettura da tastiera
Implementare un meccanismo per cui se viene eseguito il comando
’\stop’ da tastiera, il programma deve terminare immediatamente; i
file parzialmente convertiti dovranno essere cancellati, ed un
messaggio dovrà essere visualizzato per specificare quali file non sono
stati processati
Realizzare un altro thread che durante l’esecuzione del programma
stampi a intervalli di tempo abbastanza regolari la situazione di
avanzamento (es. Processando file.txt: 7263 / 14029 byte
processati) sempre rispettando quanto richiesto sull’IO su schermo
Stefano Brocchi
Laboratorio di reti I: Il multithreading
22 ottobre, 2008
40 / 40