Java - Programmazione Di Reti
Java - Programmazione Di Reti
Dipartimento di Informatica
Lezione n.1
LPR-B-09
JAVA: Tasks e Threads
22/9/2009
Andrea Corradini
(basato su materiale di Laura Ricci e Marco Danelutto)
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 1
PROGRAMMA DEL CORSO
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 2
PROGRAMMA DEL CORSO
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 3
MULTITHREADING: DEFINIZIONI
Definizioni:
Thread: flusso sequenziale di esecuzione
Multithreading:
• consente di definire più flussi di esecuzione (threads) all’ interno
dello stesso programma
• i threads possono essere eseguiti
• in parallelo (simultaneamente) se il programma viene eseguito su
un multiprocessor
• in modo concorrente (interleaving) se il programma viene eseguito
su un uniprocessor, ad esempio mediante time-sharing
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 4
MULTITHREADING: MOTIVAZIONI
Web Server:
Interfacce reattive:
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 5
MULTITHREADING: MOTIVAZIONI
Esempi:
progettazione di un browser : mentre viene caricata una pagina, mostra
un'animazione. Inoltre mentre carico la pagina posso premere il
bottone di stop ed interrompere il caricamento. Le diverse attività
possono essere associati a threads diversi.
Progettazione di applicazioni complesse che richiedono la gestione
contemporanea di più attività.
applicazioni interattive distribuite (giochi multiplayers): si devono
gestire eventi provenienti dall'interazione con l'utente, dalla rete...
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 6
TASKS E THREADS IN JAVA
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 7
THREAD IN UN PROGRAMMA JAVA
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 8
ATTIVAZIONE DI THREADS
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 9
IL TASK DECOLLO
Esempio: Implementare un task Decollo che implementi un 'conto alla
rovescia' e che, alla fine del conto, invii un segnale 'Via!'
public class Decollo implements Runnable {
int countDown = 10; // Predefinito
private static int taskCount = 0;
final int id= taskCount ++; // identifica il task
public Decollo( ) { }
public Decollo (int countDown) {
this.countDown = countDown; }
public String status ( ) {
return "#" + id + "(" +
(countDown > 0 ? countDown: "Via!!!")+"),"; }
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 10
IL TASK DECOLLO
public void run( ) {
while (countDown-- > 0){
System.out.print(status( ));
try{ Thread.sleep(100);}
catch(InterruptedException e){ }
}}}
public class MainThread {
public static void main(String[] args){
decollo d= new Decollo(); d.run( );
System.out.println ("Aspetto il decollo");}}
OutputGenerato
#0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(Via!!!),Aspetto il decollo
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 11
UN TASK NON E' UN THREAD!
• NOTA BENE: Nell'esempio precedente non viene creato alcun thread per
• Il metodo run( ) viene eseguito all'interno del thread main, attivato per il
programma principale
non si attiva alcun thread ma si esegue il task definito dal metodo run( )
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 12
DECOLLO IN UN THREAD INDIPENDENTE
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 13
DECOLLO IN PIU' THREAD
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 14
LA CLASSE java.lang.Thread
La classe java.lang.Thread contiene membri per:
• costruire un thread interagendo con il sistema operativo ospite
• attivare, sospendere, interrompere i thread
• non contiene i metodi per la sincronizzazione tra i thread, che sono
definiti in java.lang.Object.
Costruttori:
• Vari: differiscono per parametri utilizzati (esempio: task da eseguire,
nome del thread, gruppo cui appartiene il thread: vedere 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
Lezione 1: JAVA Tasks e Threads Andrea Corradini 15
LA CLASSE java.lang.Thread: start()
Il metodo start( )
• segnala allo schedulatore della JVM che il thread può essere attivato
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 16
LA CLASSE java.lang.Thread: run()
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 17
ESTENSIONE DELLA CLASSE THREADS
classe Thread
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 18
DECOLLO COME SOTTOCLASSE DI THREAD
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 19
GERARCHIA DELLE CLASSI
• Thread estende Object e implementa l'interfaccia Runnable
• DecolloThread estende Thread e sovrascrive il metodo run() di
Thread
Object Runnable
Thread
implements
DecolloThread
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 20
QUANDO E' NECESSARIO USARE LA RUNNABLE
In JAVA una classe può estendere una solo altra classe (eredità singola)
⇒
La classe i cui oggetti devono essere eseguiti come thread non può
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 21
GESTIONE DEI THREADS
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 22
ESERCIZIO 1
• Scrivere un programma JAVA che attivi K thread, chiamati “T1”, “T2”, ...,
“TK”. Tutti i thread sono caratterizzati dallo stesso comportamento: ogni
thread stampa i primi N numeri naturali, senza andare a capo (K e N sono
dati in input dall'utente). Accanto ad ogni numero deve essere visualizzato il
nome del thread che lo ha generato, ad esempio usando il formato “: n [Tk]
:”. Tra la stampa di un numero e quella del numero successivo ogni thread
deve sospendersi per un intervallo di tempo la cui durata è scelta in modo
casuale tra 0 e 1000 millisecondi.
• Sviluppare due diverse versioni del programma che utilizzino le due tecniche
per l'attivazione di threads presentate in questa lezione.
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 23
COME INTERROMPERE UN THREAD
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 24
COME INTERROMPERE UN THREAD
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 25
COME INTERROMPERE UN THREAD
• Il metodo interrupt( ):
interrompe il thread causando una InterruptedException se era sospeso
(con wait(), sleep(), join(), I/O)
altrimenti imposta a true un flag nel descrittore del thread
E' possibile testare il valore del flag mediante:
public static boolean interrupted ( ) STATIC !!!
restituisce il valore del flag (relativo al thread in esecuzione); riporta il
valore del flag a false
public boolean isInterrupted ( )
restituisce il valore del flag, relativo al thread su cui è invocato
Nota: se esiste un interrupt pendente al momento dell'esecuzione della
sleep( ), viene sollevata immediatamenete una InterruptedException.
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 26
ESERCIZIO 2: INTERROMPERE UN THREAD
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 27
Esercizio 3: 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 due argomenti:
un parametro che indica il grado di accuratezza (accuracy) per il
calcolo di π
il tempo massimo di attesa dopo cui il programma principale
interrompe il 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, oppure
2) la differenza tra il valore stimato di π ed il valore Math.PI (della
libreria Java) è minore di accuracy
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 28
PRIORITA' DEI THREADS
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 29
THREAD CON DIVERSE PRIORITA'
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 30
THREAD PRIORITY: Definizione dei task
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 31
THREAD PRIORITY: il main
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 32
THREAD PRIORITY: Un possibile output
thread B ha priorita' 2
thread D ha priorita' 7
thread C ha priorita' 7
thread A ha priorita' 8
thread B ha priorita' 2
thread D ha priorita' 7
thread A ha priorita' 8
thread C ha priorita' 7
main ha priorita' 5
thread B ha priorita' 2
thread D ha priorita' 7
thread A ha priorita' 3
thread C ha priorita' 7
thread B ha priorita' 2
thread D ha priorita' 7
thread A ha priorita' 3
thread C ha priorita' 7
U
Lezione 1: JAVA Tasks e Threads Andrea Corradini 33
Università degli Studi di Pisa
Dipartimento di Informatica
Lezione n.2
LPR-B-09
Thread Pooling e Callable
29/9-6/10/2009
Andrea Corradini
U
Lezione 2: JAVA pooling Andrea Corradini 1
ATTENDERE LA TERMINAZIONE DI UN THREAD:
METODO join()
Un thread J può invocare il motodo join( ) su un oggetto T di tipo thread
J rimane sospeso sulla join( ) fino alla terminazione di T.
Quando T termina, J riprende l'esecuzione con l'istruzione successiva alla
join( ).
Un thread sospeso su una join( ) può essere interrotto da un altro thread
Il metodo può essere utilizzato nel main per attendere la terminazione di
U
Lezione 2: JAVA pooling Andrea Corradini 2
JOINING A THREAD
U
Lezione 2: JAVA pooling Andrea Corradini 3
JOINING A THREAD
public class Joiner extends Thread {
private Sleeper sleeper;
public Joiner(String name, Sleeper sleeper){
super(name);
this.sleeper = sleeper;
start( ); }
public void run( ){
try{
sleeper.join( );
}catch(InterruptedException e) {
System.out.println("Interrotto"); return; }
System.out.println(getName( )+" join completed"); }}
U
Lezione 2: JAVA pooling Andrea Corradini 4
JOINING A THREAD
public class Joining {
public static void main(String[ ] args){
Sleeper assonnato = new Sleeper("Assonnato", 1500);
Sleeper stanco = new Sleeper("Stanco", 1500);
new Joiner("WaitforAssonnato", assonnato);
new Joiner("WaitforStanco", stanco);
stanco.interrupt(); } }
Output:
Stanco è stato interrotto
WaitforStanco join completed
Assonnato è stato svegliato normalmente
WaitforAssonnato join completed
U
Lezione 2: JAVA pooling Andrea Corradini 5
THREAD POOLING: CONCETTI FONDAMENTALI
• Uno stesso thread può essere utilizzato per eseguire diversi tasks, durante la
sua vita.
dall'utente.
U
Lezione 2: JAVA pooling Andrea Corradini 6
THREAD POOLING: MOTIVAZIONI
U
Lezione 2: JAVA pooling Andrea Corradini 7
THREAD POOLING: USO
L'utente
U
Lezione 2: JAVA pooling Andrea Corradini 8
THREAD POOLING: IL GESTORE
U
Lezione 2: JAVA pooling Andrea Corradini 9
LIBRERIA java.util.concurrent
U
Lezione 2: JAVA pooling Andrea Corradini 10
CREARE UN THREADPOOL EXECUTOR
U
Lezione 2: JAVA pooling Andrea Corradini 11
ESEMPI: IL TASK
public class TakeOff implements Runnable{
int countDown = 3; // Predefinito
public String status( ){
return "#" + Thread.currentThread() +
"(" + (countDown > 0 ? countDown: "Via!!!") + "),";
}
public void run( ) {
while (countDown-- > 0){
System.out.println(status());
try{ Thread.sleep(100);}
catch(InterruptedException e){ }
}
}}
U
Lezione 2: JAVA pooling Andrea Corradini 12
THREAD POOLING: ESEMPIO 1
import java.util.concurrent.*;
public class Esecutori1 {
public static void main(String[ ] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i=0; i<3; i++) {
exec.execute(new TakeOff( )); } } }
newCachedThreadPool ( ) crea un pool in cui quando viene sottomesso un task
• viene creato un nuovo thread se tutti i thread del pool sono occupati
nell'esecuzione di altri tasks.
• viene riutilizzato un thread che ha terminato l'esecuzione di un task
precedente, se disponibile
Se un thread rimane inutilizzato per 60 secondi, la sua esecuzione termina e
viene rimosso dalla cache.
U
Lezione 2: JAVA pooling Andrea Corradini 13
ESEMPIO1: OUTPUT
#Thread[pool-1-thread-2,5,main](2)
#Thread[pool-1-thread-1,5,main](2)
#Thread[pool-1-thread-3,5,main](2)
#Thread[pool-1-thread-3,5,main](1),
#Thread[pool-1-thread-2,5,main](1),
#Thread[pool-1-thread-1,5,main](1)
#Thread[pool-1-thread-2,5,main](Via!!!),
#Thread[pool-1-thread-1,5,main](Via!!!)
#Thread[pool-1-thread-3,5,main](Via!!!),
U
Lezione 2: JAVA pooling Andrea Corradini 14
THREAD POOLING: ESEMPIO 2
import java.util.concurrent.*;
public class Esecutori2 {
public static void main(String[]args){
ExecutorService exec = Executors.newCachedThreadPool();
for (int i=0; i<3; i++){
exec.execute(new TakeOff( ));
try {Thread.sleep (4000);}
catch(InterruptedException e) { } } } }
U
Lezione 2: JAVA pooling Andrea Corradini 15
ESEMPIO 2: OUTPUT
#Thread[pool-1-thread-1,5,main](2)
#Thread[pool-1-thread-1,5,main](1),
#Thread[pool-1-thread-1,5,main](Via!!!),
#Thread[pool-1-thread-1,5,main](2)
#Thread[pool-1-thread-1,5,main](1)
#Thread[pool-1-thread-1,5,main](Via!!!)
#Thread[pool-1-thread-1,5,main](2)
#Thread[pool-1-thread-1,5,main](1)
#Thread[pool-1-thread-1,5,main](Via!!!),
U
Lezione 2: JAVA pooling Andrea Corradini 16
THREAD POOLING: ESEMPIO 3
import java.util.concurrent.*;
U
Lezione 2: JAVA pooling Andrea Corradini 17
ESEMPIO 3: OUTPUT
#Thread[pool-1-thread-1,5,main](2),
#Thread[pool-1-thread-2,5,main](2),
#Thread[pool-1-thread-2,5,main](1),
#Thread[pool-1-thread-1,5,main](1),
#Thread[pool-1-thread-1,5,main](Via!!!),
#Thread[pool-1-thread-2,5,main](Via!!!),
#Thread[pool-1-thread-1,5,main](2),
#Thread[pool-1-thread-1,5,main](1),
#Thread[pool-1-thread-1,5,main](Via!!!),
U
Lezione 2: JAVA pooling Andrea Corradini 18
THREAD POOL EXECUTOR
package java.util.concurrent;
public class ThreadPoolExecutor implements ExecutorService{
public ThreadPoolExecutor ( int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue <Runnable> workqueue);
... }
• crea un oggetto di tipo ExecutorService
• consente di definire gestori di thread pool con una politica di gestione
personalizzata
U
Lezione 2: JAVA pooling Andrea Corradini 19
THREAD POOL EXECUTOR
U
Lezione 2: JAVA pooling Andrea Corradini 20
THREAD POOL: GESTIONE DINAMICA
U
Lezione 2: JAVA pooling Andrea Corradini 21
THREAD POOL: GESTIONE DINAMICA
U
Lezione 2: JAVA pooling Andrea Corradini 22
THREAD POOL: GESTIONE DINAMICA
U
Lezione 2: JAVA pooling Andrea Corradini 23
THREAD POOL: GESTIONE DINAMICA
U
Lezione 2: JAVA pooling Andrea Corradini 24
THREAD POOL: TIPI DI CODA
– E' sempre possibile accodare un nuovo task, nel caso in cui tutti i tasks
attivi nell'esecuzione di altri tasks
U
Lezione 2: JAVA pooling Andrea Corradini 25
THREAD POOLING: UN ESEMPIO
• Dato un intero K, si vuole calcolare, per ogni valore n < K il valore dell'n-
esimo numero di Fibonacci
U
Lezione 2: JAVA pooling Andrea Corradini 26
FIBONACCI TASK (I)
U
Lezione 2: JAVA pooling Andrea Corradini 27
FIBONACCI TASK (II)
U
Lezione 2: JAVA pooling Andrea Corradini 28
FIBONACCI THREAD POOL
import java.util.concurrent.*;
public class ThreadPoolTest {
public static void main (String [] args){
int nTasks = Integer.parseInt(args[0]); // # di tasks da eseguire
// dimensione del core pool
int corePoolSize = Integer.parseInt(args[1]);
// massima dimensione del pool
int maxPoolSize = Integer.parseInt(args[2]);
ThreadPoolExecutor tpe = new ThreadPoolExecutor (corePoolSize,
maxPoolSize,
50000L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>( ) );
U
Lezione 2: JAVA pooling Andrea Corradini 29
FIBONACCI THREAD POOL
tpe.execute(tasks[i]);
tpe.shutdown();
}
}
U
Lezione 2: JAVA pooling Andrea Corradini 30
GESTIONE DINAMICA: ESEMPI
U
Lezione 2: JAVA pooling Andrea Corradini 31
GESTIONE DINAMICA: ESEMPI
U
Lezione 2: JAVA pooling Andrea Corradini 32
GESTIONE DINAMICA: ESEMPI
(CONTINUA)
U
Lezione 2: JAVA pooling Andrea Corradini 33
GESTIONE DINAMICA: ESEMPI
U
Lezione 2: JAVA pooling Andrea Corradini 34
GESTIONE DINAMICA:ESEMPI
(CONTINUA)
U
Lezione 2: JAVA pooling Andrea Corradini 35
GESTIONE DINAMICA: ESEMPI
U
Lezione 2: JAVA pooling Andrea Corradini 36
GESTIONE DINAMICA:ESEMPI
(CONTINUA)
U
Lezione 2: JAVA pooling Andrea Corradini 37
TERMINAZIONE DI THREADS
U
Lezione 2: JAVA pooling Andrea Corradini 38
TERMINAZIONE DI EXECUTORS
• void shutdown( )
• List<Runnable> shutdownNow( )
• boolean isShutdown( )
• boolean isTerminated( )
U
Lezione 2: JAVA pooling Andrea Corradini 39
TERMINAZIONE DI EXECUTORS
U
Lezione 2: JAVA pooling Andrea Corradini 40
CALLABLE E FUTURE
U
Lezione 2: JAVA pooling Andrea Corradini 41
L'INTERFACCIA CALLABLE
U
Lezione 2: JAVA pooling Andrea Corradini 42
CALLABLE: UN ESEMPIO
Definire un task T che calcoli una approssimazione di π, mediante la serie di
Gregory-Leibniz (vedi lezione precedente). T restituisce il valore calcolato
quando la differenza tra l'approssimazione ottenuta ed il valore di Math.PI
risulta inferiore ad una soglia precision. T deve essere eseguito in un thread
indipendente.
import java.util.concurrent.*;
public class Pigreco implements Callable<Double>{
private Double precision;
public Pigreco (Double precision) {this.precision = precision;};
public Double call ( ){
Double result = <calcolo dell'approssimazione di π>
return result;
}}}
U
Lezione 2: JAVA pooling Andrea Corradini 43
L'INTERFACCIA FUTURE
threads:
U
Lezione 2: JAVA pooling Andrea Corradini 44
L'INTERFACCIA FUTURE
U
Lezione 2: JAVA pooling Andrea Corradini 45
CALLABLE E FUTURE: UN ESEMPIO
import java.util.*;
import java.util.concurrent.*;
public class FutureCallable {
public static void main(String args[])
double precision = ........;
Pigreco pg = new Pigreco(precision);
FutureTask <Double> task= new FutureTask <Double>(pg);
Thread t = new Thread(task);
t.start();
U
Lezione 2: JAVA pooling Andrea Corradini 46
CALLABLE E FUTURE: UN ESEMPIO
try{
double ris = task.get(1000L, TimeUnit.MILLISECONDS);
System.out.println("valore di isdone" + task.isDone());
System.out.println(ris + "valore di pigreco");
}
catch(ExecutionException e) { e.printStackTrace();}
catch(TimeoutException e)
{ e.printStackTrace();
System.out.println("tempo scaduto");
System.out.println("valore di isdone" + task.isDone());}
catch(InterruptedException e){ } } }
U
Lezione 2: JAVA pooling Andrea Corradini 47
THREAD POOLING CON CALLABLE
precedenti
U
Lezione 2: JAVA pooling Andrea Corradini 48
THREAD POOLING CON CALLABLE
import java.util.*;
import java.util.concurrent.*;
public class futurepools {
public static void main(String args[])
ExecutorService pool = Executors.newCachedThreadPool ( );
double precision = .........;
pigreco pg = new pigreco(precision);
Future <Double> result = pool.submit(pg);
try{ double ris = result.get(1000L, TimeUnit.MILLISECONDS);
System.out.println(ris+"valore di pigreco");}
catch(...........){ }..............}}
U
Lezione 2: JAVA pooling Andrea Corradini 49
Università degli Studi di Pisa
Dipartimento di Informatica
Lezione n.3
LPR-B-09
Threads: Sincronizzazione e
Mutua Esclusione
6/10/2009
Andrea Corradini
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 1
SULLA TERMINAZIONE: THREAD DEMONI
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 2
TERMINAZIONE: THREAD DEMONI
public class SimpleDaemon extends Thread {
public SimpleDaemon ( ) {
setDaemon(true);
start( ); }
public void run( ) {
while(true) {
try {
sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);}
System.out.println("mi sono svegliato"+this);
} }
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 3
TERMINAZIONE: THREAD DEMONI
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 4
GRUPPI DI THREAD
• Alcuni programmi contengono un gran numero di thread. Può essere utile
organizzare i thread in una struttura gerarchica in base alle loro
funzionalità.
• Esempio: un browser attiva molti thread il cui compito è scaricare le
immagini contenute in una pagina web. Se l'utente preme il pulsante
stop(), è comodo utilizzare un metodo per interrompere tutti i threads
simultaneamente.
• Gruppi di thread: sono insiemi di thread e di (sotto)gruppi di thread,
raggruppati per esempio in base alle loro funzionalità, in modo che si
possa lavorare su tutti threads di un gruppo simultaneamente.
ThreadGroup g = new ThreadGroup("GruppoPadre");
ThreadGroup f = new ThreadGroup(g, "GruppoFiglio");
Thread t1 = new Thread(g, aTask, "T1");
Thread t2 = new Thread(g, anotherTask, "T2");
............
g.interrupt( ); // interrompe tutti i thread del gruppo
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 5
CONDIVISIONE RISORSE TRA THREADS
• Più thread attivati da uno stesso programma possono condividere un
insieme di oggetti. Schema tipico: gli oggetti vengono passati al
costruttore del thread:
public class OggettoCondiviso { ........ }
public class Condivisione extends Thread {
OggettoCondiviso oc;
public Condivisione (OggettoCondiviso oc) {this.oc = oc;};
public void run (){ ...... };
public static void main(String args[ ]){
OggettoCondiviso oc = new OggettoCondiviso();
new Condivisione(oc).start();
new Condivisione(oc).start(); }
}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 6
ACCESSO A RISORSE CONDIVISE
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 7
ACCESSO A RISORSE CONDIVISE
public interface ValueGenerator {
public int next( ); }
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 8
ACCESSO A RISORSE CONDIVISE
import java.util.concurrent.*;
public class ThreadTester implements Runnable {
private ValueGenerator gen;
public ThreadTester(ValueGenerator gen) {this.gen = gen;}
public void run( ) {
for (int i = 0; i < 5; i++){
int val= gen.next();
if (val % 2 !=0) System.out.println(Thread.currentThread( )+"errore"+val);
else System.out.println(Thread.currentThread( )+"ok"+val); }}
public static void test(ValueGenerator gen, int count){
ExecutorService exec= Executors.newCachedThreadPool();
for (int i=0; i<count; i++){
exec.execute(new ThreadTester(gen));};
exec.shutdown( ); }}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 9
ACCESSO A RISORSE CONDIVISE
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 10
RACE CONDITION
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 11
RACE CONDITION e THREAD SAFETY
• Nel nostro caso la race condition (corsa critica) è dovuta alla possibilità
che un thread invochi il metodo next( ) e venga deschedulato prima di
avere completato l'esecuzione del metodo
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 12
RACE CONDITION IN SINGOLA ISTRUZIONE
• Race Condition: si può verificare anche nella esecuzione di una singola
istruzione di assegnamento
• Consideriamo un'istruzione che incrementa una variabile intera:
count = count + 1; o count++;
• L'istruzione può essere elaborata come segue
1) il valore di count viene caricato in un registro
2) si somma 1
3) si memorizza il risultato in count
• Un thread T potrebbe eseguire i passi 1), 2) e poi venire deschedulato,
• Viene quindi schedulato un secondo thread Q che esegue tutta l'istruzione
• T esegue il passo 3) assegnando a count il valore che già contiene: un
aggiornamento si è perso.
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 13
Esercizio 1
Si scriva un programma Java che dimostri che si possono verificare delle race
conditions anche con una singola istruzione di incremento di una variabile.
Scrivere una classe Counter che offre un metodo next() che
incrementa una variabile locale, e un metodo getCount() che ne
restituisce il valore.
Scrivere un task TaskCounter che implementa Callable e che riceve nel
costruttore un Counter e un intero n. Il task invoca la next() del
Counter un numero casuale di volte compreso tra n/2 e n, e restituisce
il numero casuale calcolato.
Il main crea un Counter e un pool di threads, in cui esegue M copie di
TaskCounter passando a ognuna di esse il Counter e un valore N; quindi
stampa la somma dei valori restituiti dagli M threads, e il valore finale
del contatore ottenuto con getCount(): se questi due valori sono
diversi c'è stata una race condition. M e N devono essere forniti
dall'utente.
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 14
RACE CONDITION: LAZY INITIALIZATION
Un altro esempio di una classe non thread safe
public class LazyInitRace {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance( ){
if (instance == null)
instance = new ExpensiveObject();
return instance:
}}
• Lazy Initialization =
alloca un oggetto solo se non esiste già un'istanza di quell'oggetto
deve assicurare che l'oggetto venga inizializzato una sola volta
getInstance( ) deve restituire sempre la stessa istanza
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 15
RACE CONDITIONS: ESEMPI
public class LazyInitRace {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance( ){
if (instance == null)
instance = new ExpensiveObject();
return instance:
}}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 16
JAVA: MECCANISMI DI LOCK
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 17
JAVA: IL COMANDO synchronized
• Sincronizzazione di un blocco:
synchronized (obj)
{ // blocco di codice che accede o modifica l'oggetto
}
• L'oggetto obj può essere quello su cui è stato invocato il metodo che
contiene il codice (this) oppure un altro oggetto
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 18
JAVA: RENDERE ATOMICO IL METODO NEXT
public class EvenGenerator implements ValueGenerator{
private int currentEvenValue = 0;
public int next( ){
synchronized(this){
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;} } }
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 19
JAVA 1.5: LOCK ESPLICITI
import java.util.concurrent.locks.*;
class X {
private final ReentrantLock mylock = new ReentrantLock( );
// .
.public void m( ) {
mylock.lock( ); // block until condition holds
try {
// ... method body
} finally {lock.unlock( ) } } }
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 20
JAVA 1.5: LOCK ESPLICITI
• Vediamo un'altra versione del nostro esempio con lock esplicito:
import java.util.concurrent.locks.*;
public class LockingEvenGenerator implements ValueGenerator {
private int currentEvenValue = 0;
ReentrantLock evenlock=new ReentrantLock( );
public int next( ) {
try {
evenlock.lock( );
++currentEvenValue;
Thread.yield ( );
++currentEvenValue;
return currentEvenValue;
} finally {evenlock.unlock( );}}}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 21
JAVA: MECCANISMO DEI LOCK
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 22
I METODI SYNCHRONIZED
• La parola chiave synchronized nella intestazione di un metodo ha
l'effetto di serializzare gli accessi al metodo
• Implementazione:
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 23
I METODI SYNCHRONIZED
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 24
I METODI SYNCHRONIZED
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 25
I METODI SYNCHRONIZED
L'esempio seguente crea due istanze dell'oggetto EvenValue1( ) e le passa a
due thread distinti. Si considera la versione non sincronizzata del metodo
next( )
public class EvenValue1 implements ValueGenerator{
private int currentEvenValue = 0;
public int next( ){ ++currentEvenValue; ++currentEvenValue;
return currentEvenValue; } }
public class SynchroTest {
public static void main(String args[ ]){
ValueGenerator eg1 = new EvenValue1();
ValueGenerator eg2 = new EvenValue1();
ThreadTester1.test(eg1,eg2);}}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 26
I METODI SYNCHRONIZED
import java.util.concurrent.*;
import java.util.Random;
public class ThreadTester1 implements Runnable{
private ValueGenerator g;
public ThreadTester1 (ValueGenerator g) {this.g = g;}
public void run( ){
for (int i=0; i<5; i++){
int val= g.next();
if (val % 2 !=0)
System.out.println(Thread.currentThread() + "errore" + val);
else System.out.println(Thread.currentThread() + "ok" + val);
try {Thread.sleep((int) Math.random() * 1000);}
catch (Exception e) { }; }}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 27
I METODI SYNCHRONIZED
public static void test(ValueGenerator g1, ValueGenerator g2){
ExecutorService exec= Executors.newCachedThreadPool();
exec.execute(new tester(g1));
exec.execute(new tester(g2)); exec.shutdown() } }
Thread[pool-1-thread-1,5,main]ok10
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 28
Esercizio 2
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 29
LOCK RIENTRANTI
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 30
LOCK RIENTRANTI
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 31
REENTRANT LOCK E EREDITARIETA'
public class ReentrantExample {
public synchronized void doSomething( ) {
.............} }
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 32
MUTUA ESCLUSIONE: RIASSUNTO
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 33
ESERCIZIO 3: ANCORA RACE CONDITIONS
Simulare il comportamento di una banca che gestisce un certo numero di conti
correnti. In particolare interessa simulare lo spostamento di denaro tra due
conti correnti.
Ad ogni conto è associato un thread T che implementa un metodo che consente
di trasferire una quantità casuale di denaro tra il conto servito da T ed un
altro conto il cui identificatore è generato casualmente.
• sviluppare una versione non thread safe del programma in modo da
evidenziare un comportamento scorretto del programma
• definire 3 versioni thread safe del programma che utilizzino,
rispettivamente
Lock esplicite
Blocchi sincronizzati
Metodi sincronizzati
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 34
THREADS COOPERANTI: I MONITOR
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 35
THREADS COOPERANTI: I MONITOR
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 36
THREADS COOPERANTI: I MONITOR
JAVA
● non supporta variabili di condizione
● assegna al programmatore il compito di gestire le condizioni
mediante variabili del programma
● definisce meccanismi che consentono ad un thread
● di sospendersi wait( ) in attesa che sia verificata una
condizione
● di segnalare con notify( ), notifyall ( ) ad un altro/ad altri
threads sospesi che una certa condizione è verificata
● Per ogni oggetto implementa due code:
● una coda per i thread in attesa di acquisire il lock
● una coda in cui vengono memorizzati tutti i thread sospesi con
la wait( ) (in attesa del verificarsi di una condizione).
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 37
THREADS COOPERANTI: I MONITOR
MONITOR
CAMPI DELL'OGGETTO
Coda dei threads in
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 38
ESEMPIO: PRODUTTORE/CONSUMATORE
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 39
I METODI WAIT/NOTIFY
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 40
WAIT, NOTIFY E IL LOCK
wait( )
rilascia il lock sull'oggetto prima di sospendere il thread corrente
quando risvegliato da una notify( ), il thread compete per riacquisire il
lock
notify( )
risveglia uno dei thread (non si sa quale...) nella coda di attesa
dell'oggetto; non rilascia immediatamente il lock
notifyAll( )
risveglia tutti i threads in attesa sull'oggetto; non rilascia il lock
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 41
WAIT E NOTIFY
• Il metodo wait() permette di attendere il cambiamento di una condizione
sullo stato dell'oggetto “fuori dal monitor”, in modo passivo
• Evita il controllo ripetuto di una condizione (polling)
• A differenza di sleep() e di yield() rilascia il lock sull'oggetto
• Quando ci si sospende su di una condizione, occorre controllarla quando si
viene risvegliati:
synchronized(obj){
while (<condizione non soddisfatta>)
obj.wait();
... // esegui l'azione per cui richiedevi la condizione
}
• L'invocazione di un metodo wait(), notify(), notifyall() fuori da un metodo
synchronized solleva l'eccezione IllegalMonitorException( ): prima di
invocare questi metodi occorre aver acquisito il lock su un oggetto condiviso
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 42
PRODUTTORE/CONSUMATORE: IL BUFFER
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 43
IL PRODUTTORE
public class Producer implements Runnable {
private Buffer buf;
public Producer(Buffer buf){ this.buf = buf; }
public void run() {
try{
while(true){
int next = (int)(Math.random() * 10000);
buf.put(next);
System.out.println("[Producer] Put " + next);
Thread.sleep((int)(Math.random() * 500)); }
} catch (InterruptedException e){
System.out.println("[Producer] Interrupted");
}}}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 44
IL CONSUMATORE
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 45
PRODUTTORE/CONSUMATORE: IL MAIN
import java.util.concurrent.*;
public class TestProducerConsumer {
public static void main(String[] args) {
Buffer buf = new Buffer(5);
Consumer cons = new Consumer(buf);
Producer prod = new Producer(buf);
ExecutorService exec = Executors.newFixedThreadPool(2);
exec.execute(cons);
exec.execute(prod);
try { Thread.sleep(10000); } catch (InterruptedException e) { }
exec.shutdownNow();
}}
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 46
PRODUCER/CONSUMER: OUTPUT
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 47
ESERCIZIO 4
• La classe Buffer ha una politica Last In First Out (LIFO), quindi non
preserva l'ordine. Scrivere la classe CircularBuffer che estende
Buffer e realizza una politica FIFO, gestendo l'array in modo
circolare.
• Definire le interfacce generiche Producer<E>, Consumer<E> e
Buffer<E>, che definiscono un sistema produttore/consumatore per
un generico tipo di dati E.
• Implementare le interfacce in modo che il produttore produca una
sequenza di stringhe, leggendole da un file passato come parametro al
task, e il consumatore scriva le stringhe che prende dal buffer in un
altro file.
• Nel main, creare e attivare un produttore e due o più consumatori.
Verificare che la concatenazione dei file generati dai consumatori sia
uguale, a meno dell'ordine delle righe, al file letto dal produttore.
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 48
ESERCIZIO 5 (a)
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 49
ESERCIZIO 5(b)
U
Lezione 3: Threads: Sincronizzazione e Mutua Esclusione Andrea Corradini 50
Università degli Studi di Pisa
Dipartimento di Informatica
Lezione n.4
LPR-A-09
Indirizzi IP e URL
13/10/2009
Vincenzo Gervasi
ULezione 4: Indirizzi IP e URL Vincenzo Gervasi 1
PROGRAMMAZIONE DI RETE: INTRODUZIONE
Programmazione di rete:
sviluppare applicazioni definite mediante due o più processi in esecuzione
su hosts diversi, distribuiti sulla rete. I processi cooperano per realizzare
una certa funzionalità
Cooperazione: richiede lo scambio di informazioni (comunicazione) tra i
processi
Comunicazione = Utilizza protocolli (cioè insieme di regole che i partners
della comunicazione devono seguire per poter comunicare)
Alcuni protocolli utilizzati in INTERNET:
– IP (Internet Protocol)
– TCP (Transmission Control Protocol) un protocollo connection-oriented
– UDP (User Datagram Protocol) protocollo connectionless
– Socket
– ServerSocket
– DatagramSocket
– MulticastSocket
• nslookup
import java.net.*;
import java.io.*;
protocol = http
authority = www.cli.di.unipi.it:80
host = www.cli.di.unipi.it
port = 80
path = /faq
query = null
filename = /faq
ref = null
Lezione n.6
LPR-B-09
Il protocollo UDP:
Socket e Datagram
27/10/2009
Andrea Corradini
Processo 1 Processo 2
(Mittente) dato (Destinatario)
HOST 2
HOST 1
Processo 1
dato . (Destinatario)
. HOST 1
Processo 1
(Mittente) dato .
HOST 1
Processo n
(Destinatario)
HOST n
Indirizzamento:
Connection Oriented: l’indirizzo del destinatario è specificato
al momento della connessione
Connectionless: l’indirizzo del destinatario viene specificato in
ogni pacchetto (per ogni send)
• Ordinamento dei dati scambiati:
Connection Oriented: ordinamento dei messaggi garantito
Connectionless: nessuna garanzia sull’ordinamento dei messaggi
• Utilizzo:
Connection Oriented: grossi streams di dati
Connectionless : invio di un numero limitato di dati
• il processo che esegue il Web browser esegue una connect per stabilire
una connessione con il processo che esegue il Web Server
• il Web browser esegue una send, per trasmettere una richiesta al Web
Server (operazione GET)
• il Web server esegue una receive per ricevere la richiesta dal Web
Browser, quindi a sua volta esegue una send per inviare la risposta
• i due processi eseguono una disconnect per terminare la connessione
send sincrona = completata quando i dati spediti sono stati ricevuti dal
destinatario (è stato ricevuto un ack da parte del destinatario)
il destinatario esegue nuovamente la receive, dopo un certo intervallo
di tempo (polling)
il supporto a tempo di esecuzione notifica al destinatario l’arrivo del
dato (richiesta l’attivazione di un event listener)
Timeout – meccanismo che consente di bloccarsi per un intervallo di
tempo prestabilito, poi di proseguire comunque l’esecuzione
Threads – l’operazione sincrona può essere effettuate in un thread.
Se il thread si blocca su una send/receive sincrona, l’applicazione può
eseguire altri thread.
Nel caso di receive sincrona, gli altri threads ovviamente non devono
richiedere per l’esecuzione il valore restituito dalla receive
Socket è una astrazione che indica una “presa ” a cui un processo si può
collegare per spedire dati sulla rete. Al momento della creazione un socket
viene collegato ad una porta.
Socket
Lungh.
IP Version Header TOS Lungh. Datagram 0
frammentazione Identific. Flag Offset 32
Indirizzo Mittente 96
Opzioni 160
160/
Dati 192+
• Indirizzo mittente/destinatario
64
DATI
Altro costruttore:
ricezione di un pacchetto.
• il payload del pacchetto (la parte che contiene i dati) viene copiato nel
buffer [a partire dalla posizione offset] al momento della ricezione.
• la copia del payload termina quando l'intero pacchetto è stato copiato
oppure, se la lunghezza del pacchetto è maggiore di length, quando length
bytes sono stati copiati
• il parametro length
prima della copia, indica il numero massimo di bytes che possono essere
copiati nel buffer
dopo la copia, indica il numero di bytes effettivamente copiati.
offset 4 length 6
0 1 2 3 4 5 6 7 8 9 10 ...
U Lezione 6: Il Protocollo UDP, sockets e datagrams Andrea Corradini 29
INVIARE E RICEVERE PACCHETTI
Invio di pacchetti
• sock.send (dp)
Ricezione di pacchetti
•
sock.receive(buffer)
Server Client
receive
richiesta in esecuzione
send
bloccato
risposta
send
receive
• Nel caso in cui l'intervallo di tempo scada, prima che venga ricevuto un
pacchetto dal socket, viene sollevata una eccezione di tipo
InterruptedIOException
• Questi buffers sono gestiti dal sistema operativo, non dalla JVM. La loro
dimensione dipende dalla piattaforma su cui il programma è in esecuzione
import java.net.*;
public ByteArrayOutputStream ( )
public ByteArrayOutputStream (int size)
• gli oggetti di questa classe rappresentano stream di bytes tali che ogni dato
scritto sullo stream viene riportato in un buffer di memoria (array di byte)
a dimensione variabile (dimensione di default = 32 bytes).
• quando il buffer si riempie la sua dimensione viene raddoppiata
• quindi consente di accedere ad un array di byte come se fosse uno stream;
l'array può essere estratto con il metodo toByteArray()
puntatore all’ultimo
elemento inserito
BUFFER
ByteArrayOutputStream
• Trasmissione connectionless:
ByteArrayOutputStream, consentono la conversione di uno stream di
bytes in un array di bytes da spedire con i pacchetti UDP
ByteArrayInputStream, converte un array di bytes in uno stream di
byte. Consente di manipolare più agevolmente i bytes
rete
dati
DataOutputStream ByteArrayOutputStream ByteArray Pacchetto
Buffer
• baos.reset ( )
• Esempio:
Esercizio:
Scrivere un'applicazione composta da un processo Sender ed un processo
Receiver. Il Receiver riceve da linea di comando la porta su cui deve porsi in
attesa. Il Sender riceve da linea di comando una stringa e l’indirizzo del
Receiver (indirizzo IP + porta), e invia al Receiver la stringa. Il Receiver riceve
la stringa e stampa, nell'ordine, la stringa ricevuta, l'indirizzo IP e la porta del
mittente.
Considerare poi i seguenti punti:
• cosa cambia se mando in esecuzione prima il Sender, poi il Receiver
rispetto al caso in cui mando in esecuzione prima il Receiver?
• nel processo Receiver, aggiungere un time-out sulla receive, in modo che
la receive non si bocchi per più di 5 secondi. Cosa accade se attivo il
receiver, ma non il sender?
Lezione n.7
LPR-B-08
UDP: Costruzione di
pacchetti, e esercizi avanzati
10/11/2009
Andrea Corradini
Consente di convertire un oggetto E TUTTI QUELLO DA ESSO
RAGGIUNGIBILI in una sequenza di bytes.
• Tale sequenza può essere utilizzata per ricostruire l’oggetto e il contesto.
• L’oggetto e tutti quelli raggiungibili devono essere definiti in classi che
implementi l’interfaccia Serializable, che non ha metodi! Altrimenti viene
lanciata una NotSerializableException.
• Tutte le classi involucro per i tipi di dati primitivi (es: Integer, Double, ...) e
anche String implementano Serializable: quindi JAVA garantisce una
serializzazione di default per tutti i dati primitivi.
• Per serializzare uno o più oggetti si utilizzano stream di tipo
ObjectOutputStream e ObjectInputStream, e i rispettivi metodi
writeObject() e readObject().
• Il meccanismo di serializzazione può essere personalizzato, ma non lo
vediamo...
toByteArray()
ObjectOutputStream(ByteArrayOutputStream)
DatagramPacket
{oggetti}
byte[ ]
writeObject( )
send( )
DatagramSocket
receive( )
{oggetti}
DatagramPacket byte[ ]
readObject( )
ObjectInputStream(ByteArrayInputStream)
L'output del programma mostra che il vettore e il suo contenuto sono arrivati
correttamente al receiver:
class java.lang.Integer: 74
class java.lang.String: Questa e' una stringa
class java.awt.Rectangle: java.awt.Rectangle[x=3,y=4,width=10,height=20]
Lezione n.7
LPR-B-09
TCP: Stream Sockets
17/11/2009
Andrea Corradini
CountDownClient CountDownServer
n
.
n,n-1,n-2,...
CountDownClient CountDownServer
n
sock1
n,n-1,n-2,...
.
sock2
●
Posso utilizzare sockets diversi per la spedizione/ricezione
●
In questo caso può accadere che sock2 non sia ancora stato creato
quando CountDownServer inizia ad iniziare la sequenza di numeri
●
E' possibile che il CountDownClient si blocchi sulla receive poiché i dati
inviati dal CountDownServer sono stati inviati prima della creazione del
socket e quindi sono andati persi
Client1
SIP = Indirizzo IP del Server Active Socket
PL=Porta Locale
Listening
Socket PR = Porta Remota
Client2
Active Socket
PL=Porta Locale
Client1
SIP = Indirizzo IP del Server Active Socket
PL=Porta Locale
Listening
Socket PR = Porta Remota
Client2
Active Socket
Active Socket
Active Socket
PL=Porta Locale
public Socket (String host, int port, InetAddress locIA, int locPort) ....
– tenta di creare una connessione verso l’host host, sulla porta port,
dalla interfaccia locale localIA, dalla porta locale locPort
– utile per macchine dotate di più schede di rete, ad esempio un host con
due indirizzi IP, uno visibile da Internet, l’altro solo a livello di rete
locale.
– il DNS viene interrogato una sola volta, prima di entrare nel ciclo di
scanning, dalla InetAddress.getByName
– si usa l’InetAddress invece del nome dell’host per costruire i sockets
Uno 'snapshot' dei socket a cui sono state associate connessioni attive può
essere ottenuto mediante l'utility netstat (network statistics), disponibile
sui principali sistemi operativi
import java.net.*;
Per accettare una nuova connessione dal listening socket si usa il metodo:
public Socket accept( ) throws IOException
Echo Server
byte [ ] byte [ ]
Send-Q Recv-Q
sugli/dagli streams.
– La write( ) trasferisce i byte nel Send-Q buffer, se esiste abbastanza
spazio nel buffer. Se non riesce a scrivere tutti i byte nel Send-Q
buffer, si blocca.
– La read( ) legge i dati disponibili nel Recv-Q al momento della
invocazione sull'InputStream. Se Recv-Q buffer non contiene dati si
blocca.
s.close();
Mittente
Destinatario
Se il ricevente esegue una read con un byte array di dimensione 4000, nella
situazione mostrata in figura, la read
• riempe completamente il byte array
• restituisce 1500 caratteri prodotti dalla seconda write( ) e 2500 dalla
terza
• alcuni bytes rimangono nel receive buffer e verranno recuperati con
una successiva read( )
• Esempio:
– un client non deve inviare ulteriori dati al socket, ma deve attendere
una risposta dal socket stesso
– Il client può chiudere lo stream di output associato al socket e
mantenere aperto lo stream di input per ricevere la risposta
compresso al client che provvede a creare un file con lo stesso nome del
file originario e con estensione gz, che contiene i dati ricevuti dal server.
socket
• Proprietà:
– SO_TIMEOUT
– SO_RCVBUF
– SO_SNDBUF
– SO_KEEPALIVE
– TCP_NODELAY
– SO_LINGER
...........
if (s.getSoTimeout( ) == 0) s.setSoTimeout(1800000);
Il timeout viene specificato in millisecondi
Quando eseguo una lettura bloccante dal socket, l'operazione si può
bloccare in modo indefinito
• SO_TIMEOUT: definisce un intervallo di tempo massimo per l'attesa
dei dati
• Nel caso in cui il time out scada prima della ricezione dei dati, viene
sollevata una eccezione
• introdotto per individuare i sockets “idle” su cui non sono stati inviati
dati per un lungo intervallo di tempo
• Per default, su ogni socket vengono spediti solo dati inviati dalla
applicazione
Algoritmo di Nagle:
sock.setTcpNoDelay(true)
Lezione n.8
LPR-B-09
TCP Sockets & Multicast
24/11/2009
Andrea Corradini
<Welcome>
<Goodbye>
ricevuto dal server supera B,l'utente abbandona l'asta, dopo aver avvertito il
Per ogni richiesta di rilancio, il server notifica al client se tale offerta può
rifiutata.
Il server deve attivare un thread diverso per ogni client che intende
partecipare all'asta.
• Questo implica che sullo stesso host possano esistere più sockets
associati allo stesso indirizzo IP ed alla stessa porta locale (il Server
Socket e tutti i Sockets associati,.....)
• La porta locale riferita nel socket deve coincidere con quella contenuta nel
segmento TCP
• Ogni campo del socket contenente una wildcard (*), può essere messo in
corrispondenza con qualsiasi valore corrispondente contenuto nel
segmento
• in questo modo un segmento spedito dal client viene ricevuto sul socket S
associato alla connessione con quel client, piuttosto che sul serversocket
perchè S risulta 'più specifico' per quel segmento
un insieme di processi formano un gruppo di multicast
un messaggio spedito da un processo a quel gruppo viene recapitato a
tutti gli altri partecipanti appartenenti al gruppo
Un processo può lasciare un gruppo di multicast quando non è più
interessato a ricevere i messaggi del gruppo
unirsi ad un gruppo di multicast (join). E’ richiesto uno schema di
indirizzamento per identificare univocamente un gruppo.
lasciare un gruppo di multicast (leave).
spedire messaggi ad un gruppo. Il messaggio viene recapitato a tutti i
processi che fanno parte del gruppo in quel momento
ricevere messaggi indirizzati ad un gruppo
uno schema di indirizzamento dei gruppi
un supporto che registri la corrispondenza tra un gruppo ed i
partecipanti
un'implementazione che ottimizzi l’uso della rete nel caso di invio di
pacchetti ad un gruppo di multicast
router2
router2
router1
router1
Server A
Server A
Milano MP
Firenze
MP
MP MP
Roma
HostB HostC
Host A Pisa
Indirizzo di multicast: indirizzo IP di classe D, che individua un
gruppo di multicast
Indirizzo di classe D- intervallo 224.0.0.0 – 239-255-255-255
1110 …..
l’indirizzo di multicast è condiviso da tutti i partecipanti al gruppo
è possibile associare un nome simbolico ad un gruppo di multicast
Esempio: 224.0.1.1 ntp.mcast.net
(network time protocol distributed service)
ALL-ROUTERS.MCAST.NET 224.0.0.2
tutti i routers della rete locale
MulticastSocket ms = null;
try{ ms = new MulticastSocket(port);
ms.joinGroup(group); // mi unisco al gruppo
byte [ ] buffer = new byte[8192];
while (true){
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ms.receive(dp); // aspetto un pacchetto
String s = new String(dp.getData()); // estraggo il messaggio
System.out.println(s);} // .lo stampo
} catch (IOException ex){System.out.println (ex);
}
il mittente specifica un valore per del TTL per i pacchetti spediti
il TTL viene memorizzato in un campo dell’header del pacchetto IP
TTL viene decrementato da ogni router attraversato
Se TTL = 0 ⇒ il pacchetto viene scartato
s.setTimeToLive(16);
Lezione n.9
LPR-B-09
RMI: Remote Method
Invocation
1/12/2009
Andrea Corradini
Client Server
richies
ta
Bloccato In elaborazione
ta
rispos
procedura
remota print(…)
print (msg)
bloccato
codice
Implementazioni RPC
• Open Network Computing Remote Procedure Call (Sun)
• Open Group Distributed Computing Environment (DCE)
• …
Object Registry
Riferimento
all’oggetto remoto Esportazione (registrazione)
Client Server
Oggetto
Invocazione metodi remoto
Interazione logica
Interazione fisica
• Pubblicazione dell'oggetto:
crea un binding (associazione)
nome simbolico oggetto/ riferimento all’oggetto
lo pubblica mediante un servizio di tipo registry (registro)
(simile ad un DNS per oggetti distribuiti)
• Attivazione del RMI registry (porta default 1099):
rmiregistry & (Linux)
start rmiregistry (Windows)
import java.rmi.*;
• Passo 1. Definire una interfaccia che includa le firme dei metodi che
possono essere invocati da remoto
import java.rmi.*;
public interface EchoInterface extends Remote {
String getEcho (String Echo) throws RemoteException; }
nome
servizio riferimento
riferimento
echo all’oggetto
throws RemoteException
• nel caso più semplice si utilizza un registry locale, attivato sullo stesso host
su cui è in esecuzione il server
• se non ci sono parametri oppure se il nome dell'host è uguale a null, allora
l'host di riferimento è quello locale
• la stessa porta va indicata sia nel client che nel server al momento del
reperimento del riferimento al registro, mediante
LocateRegistry.getRegistry
Il client:
• ricerca uno stub per l'oggetto remoto
• invoca i metodi dell’oggetto remoto come fossero metodi locali (l'unica
differenza è che occorre intercettare RemoteException)
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.*;
public class Client {
private Client( ) { }
public static void main(String[ ] args) throws Exception
{
String host = args[0];
Scanner s = new Scanner(System.in);
String next = s.next();
try {
Registry registry = LocateRegistry.getRegistry(host);
EchoInterface stub = (EchoInterface) registry.lookup("Echo");
String response = stub.getEcho(next);
System.out.println("response: " + response);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}}}
• public void vota (String nome). Accetta come parametro il nome del
candidato. Non restituisce alcun valore. Registra il voto di un candidato in
una struttura dati opportunamente scelta.
Lezione n.10
LPR-B-09
RMI CallBacks
9/12/2009
Andrea Corradini
Ma in molte applicazioni
il client è interessato ad un evento che si verifica sul server e
notifica il suo interesse al server (per esempio utilizzando RMI)
il server registra che il client è interessato in quell’evento
quando l’evento si verifica, il server notifica ai clients interessati
l’accadimento dell’event
Esempi di applicazioni:
Lato Server:
Interfaccia remota che definisce metodi per: (1) Contattare il
server: metodo SayHello( ) (2) Registrare/cancellare una callback:
Implementazione dell'interfaccia
Esportazione e pubblicazione su registry di oggetto remoto
Lato Client:
Intefaccia remota che definisce metodo remoto (callback)
Implementazione di interfaccia remota
Programma principale che:
Registra una callback presso il server: sarà usata per notificare
al client i contatti stabiliti da clients con il metodo SayHello( ).
Effettua un numero casuale di richieste del metodo SayHello( )
Cancella la propria registrazione
import java.rmi.*;
public interface CbServerInt extends Remote {
/* metodo di notifica */
public String sayHello(String name) throws RemoteException;
notifyMe(...)
è il metodo esportato dal client e che viene utilizzato dal server per
Eccezione che viene sollevata se non trova un servizio di registry su quella
porta. Esempio:
Esempio
registrazione dei clients sul server avviene nel momento del voto.