Marco Botta
Dipartimento di Informatica - Universita` degli Studi d i Torino C.so Svizzera, 185 - I-10149 Torino (Italy) e-mail: botta@d i.unito .it - URL: http://www.di.unito.it/~botta
Slide design: Matteo Baldoni
e-mail: baldoni @di.unito.it - URL: http://www.di.unito.it/~baldoni
Programmazione
Programmazione ad ad Oggetti Oggetti
Trattamento delle Eccezioni e Threads
Ingegneria del Software: Programmazione ad Oggetti 2
Trattamento delle Eccezioni Trattamento delle Eccezioni
• Una exception è una situazione anormale generata da una sequenza di codice a tempo di esecuzione (es. divisione per 0)
• Java runtime costruisce un oggetto di tipo Exception ogni volta che si verifica una situazione anormale nell’esecuzione del codice e attiva un meccanismo di gestione dell’errore
Ingegneria del Software: Programmazione ad Oggetti 3
Trattamento delle Eccezioni Trattamento delle Eccezioni
• JAVA fornisce 5 keywords per la gestione delle eccezioni
– try throw
– catch throws – finally
• try, catch e finally fanno parte dello stesso costrutto
• throw permette di generare una eccezione
• throws indica quali Exception possono essere generate da un metodo
Ingegneria del Software: Programmazione ad Oggetti 4
Trattamento delle Eccezioni Trattamento delle Eccezioni
try {
// block of code
} catch (ExceptionType1 e) {
// exception handler for ExceptionType1 } catch (ExceptionType2 e) {
//exception handler for ExceptionType2 throw (e); // re-throw exception } finally {
// code always to be executed }
class exc2 {
public static void main (String args[]) { try {
int d=0;
int a = 42/d;
} catch (ArithmeticException e) { System.out.println(“Divisione per zero”);
} } }
Ingegneria del Software: Programmazione ad Oggetti 5
Trattamento delle Eccezioni Trattamento delle Eccezioni
• Le eccezioni sono organizzate in una gerarchia di classi
• Metodi che generano eccezioni devono dichiararne il tipo nell’intestazione del metodo
double divide (int x, int y) throws ArithmeticException
• Poter gestire eventi eccezionali è molto utile e rende il codice più leggibile
FileInputStream fis;
try {
fis = new FileInputStream (“readme.txt”);
} catch (FileNotFoundException e) { fis = new FileInputStream (“default.txt”) ;
} Ingegneria del Software: Programmazione ad Oggetti 6
Trattamento delle Eccezioni Trattamento delle Eccezioni
class MyException extends Exception { private int detail;
MyException(int a) { detail = a; } public String toString()
{ return "MyException[" + detail + "]"; } }
class ExceptionDemo {
static void compute(int a) throws MyException { System.out.println("called compute(" + a + ").");
if (a > 10) throw new MyException(a);
System.out.println("normal exit.");
}
public static void main(String args[]) { try {
compute(1); compute(20);
} catch (MyException e) {
System.out. println("caught " + e.toString()); } }
}
called compute(1).
normal exit.
called compute(20).
caught MyException[20]
Ingegneria del Software: Programmazione ad Oggetti 7
Trattamento delle Eccezioni Trattamento delle Eccezioni
class FinallyDemo {
static void procA () throws RuntimeException { try {
System.out. println("inside procA");
throw new RuntimeException("demo");
} finally { System.out.println ("procA's finally"); } }
static void procB () { try {
System.out. println("inside procB");
return;
} finally { System.out.println ("procB's finally"); } }
public static void main(String args[]) { try { procA(); } catch (Exception e) {};
procB();
} }
inside procA procA’s finally inside procB procB’s finally
Ingegneria del Software: Programmazione ad Oggetti 8
Threads Threads
• Una thread è una sequenza di passi eseguiti uno alla volta
• In sistemi multi-threaded, più threads possono essere attive contemporaneamente
• Un processo può avere più sequenze di esecuzione contemporaneamente
• Due threads condividono lo stesso spazio di indirizzi
• Le threads permettono di scrivere programmi concorrenti
Ingegneria del Software: Programmazione ad Oggetti 9
Threads Threads
• Threads in JAVA sono definite da una classe Thread
– Creare un oggetto Thread
• Thread worker = new Thread();
– Configurare worker
• settare priorita`, nome, etc.
– Invocare il metodo start
• worker.start()
– Il metodo start richiama il metodo run definito per quella thread
Ingegneria del Software: Programmazione ad Oggetti 10
Threads Threads
class PingPong extends Thread { String word; // what word to print int delay; / how long to pause
PingPong(String whatToSay, int delayTime) { word = whatToSay; delay = delayTime; } public void run() {
try { for (;;) {
System.out.print(word+””);
sleep(delay); // wait until next time }
} catch (InterruptedException e) { return; } }
public static void main(String args[]) {
new PingPong (“ping”, 33).start(); // 1/30 second new PingPong (“PONG”, 100).start(); // 1/10 second }
}
ping PONG ping ping PONG ping ping ping PONG ping ping PONG ping ping ping PONG ping ping PONG ping ...
Ingegneria del Software: Programmazione ad Oggetti 11
Threads Threads
• La classe Thread implementa l’interface Runnable – dichiara un solo metodo
• public void run();
• Una Thread può essere eseguita su un qualunque oggetto che implementa Runnable
• Implementare Runnable significa definire l’implementazione del metodo run
Ingegneria del Software: Programmazione ad Oggetti 12
Threads Threads
class RunPingPong implements Runnable { String word;
int delay;
RunPingPong (String whatToSay , int delayTime) { word = whatToSay; delay = delayTime; } public void run() {
try { for (;;) {
System.out.print(word+” “);
Thread.sleep(delay);
}
} catch (InterruptedException e) { return; } }
public static void main(String args[]) { Runnable ping = new RunPingPong(“ping”, 33);
Runnable pong = new RunPingPong(“PONG”,100);
new Thread(ping).start();
new Thread(pong).start();
} }
Ingegneria del Software: Programmazione ad Oggetti 13
Threads:
Threads: priorit priorità à
class clicker implements Runnable { int click = 0;
private Thread t;
private boolean running = true;
public clicker(int p) { t = new Thread(this);
t.setPriority(p);
}
public void run() { while (running) { click++; } } public void stop() { running = false; } public void start() { t.start(); } }
• Ogni thread ha una priorità per l’esecuzione che può essere modificata
• La priorità influisce sullo scheduling delle threads
Ingegneria del Software: Programmazione ad Oggetti 14
Threads:
Threads: priorit priorità à
class HiLoPri {
public static void main(String args[]) { Thread t = Thread.currentThread();
t..setPriority(Thread.MAX_PRIORITY);
clicker hi = new clicker(Thread.NORM_PRIORITY + 2);
clicker lo = new clicker(Thread.NORM_PRIORITY - 2);
lo.start();
hi.start();
try { Thread.sleep(10000); } catch (Exception e) {};
lo.stop();
hi.stop();
System.out.println(lo.click + " vs. " + hi.click);
} }
su Windows95/NT: 304300 vs. 4066666 su Solaris: 0 vs. 3062507
• Settare la priorità non garantisce lo scheduling delle threads
Ingegneria del Software: Programmazione ad Oggetti 15
Threads:
Threads: sincronizzazione sincronizzazione
• In un ambiente multi-threaded più threads possono accedere agli stessi dati
– l’accesso ai dati deve essere sincronizzato
class Account { private double balance;
public Account(double init) { balance = init; } public double getBalance () { return balance; } public void setBalance(double amount) { balance = amount; }
}
Thread 1 Thread 2
a1 = A.getBalance ();
a1 += deposit; a2 = A. getBalance();
A. setBalance(a1); a2 += deposit;
A.setBalance(a2);
Ingegneria del Software: Programmazione ad Oggetti 16
Threads:
Threads: sincronizzazione sincronizzazione
class Callme { void call(String msg) {
System.out.print("[" + msg);
try { Thread.sleep(1000); } catch (Exception e) {};
System.out.println("]");
} }
class Caller implements Runnable { String msg;
Callme target;
public Caller(Callme t, String s)
{ target = t; msg = s; new Thread(this).start(); } public void run() { target.call(msg); }
}
class Synch {
public static void main(String args[]) { Callme target = new Callme();
new Caller(target, "Hello");
new Caller(target, "Synchronized");
new Caller(target, "World");
} }
[Hello[Synchronized[World]
] ]
Ingegneria del Software: Programmazione ad Oggetti 17
Threads:
Threads: sincronizzazione sincronizzazione
• La sincronizzazione di due threads fa si che siano eseguite in mutua esclusione
• I metodi sono dichiarati synchronized
• L’invocazione di un metodo synchronized da parte di una thread su un oggetto, attiva un lock sull’oggetto
• Un’altra thread che invochi un metodo synchronized sullo stesso oggetto è sospesa
Ingegneria del Software: Programmazione ad Oggetti 18
Threads:
Threads: sincronizzazione sincronizzazione
class Callme {
synchronized void call(String msg ) { System.out.print("[" + msg);
try { Thread.sleep(1000); } catch (Exception e) {};
System.out. println("]");
} }
class Caller implements Runnable { ...
}
class Synch {
public static void main(String args[]) { Callme target = new Callme();
new Caller(target, "Hello");
new Caller(target, "Synchronized");
new Caller(target, "World");
} }
[Hello]
[Synchronized]
[World]
Ingegneria del Software: Programmazione ad Oggetti 19
Threads:
Threads: sincronizzazione sincronizzazione
• Anche i metodi static (di classe) possono essere synchronized
• Due threads non possono eseguire metodi synchronized static sulla stessa classe
class Account { private double balance;
public Account(double init) { balance = init; }
public synchronized double getBalance() { return balance; } public synchronized void deposit(double amount)
{ balance += amount; } }
Thread 1 Thread 2
A.deposit(amount1); A.deposit(amount2);
Ingegneria del Software: Programmazione ad Oggetti 20
Threads:
Threads: sincronizzazione sincronizzazione
• E` possibile eseguire codice sincronizzato senza richiamare un metodo synchronized
– synchronized (expr) { body } – expr è un oggetto sul quale si fa il lock – body è una sequenza di istruzioni che sono
eseguite ín modo sincronizzato con altre esecuzioni
/** make all elements in the array nonnegative */
public static void abs(int[] values) { synchronized (values) {
for (int i=0; i<values.length; i++) { if (values[i]<0) values[i] = -values[i];
} } }
Ingegneria del Software: Programmazione ad Oggetti 21
Threads:
Threads: sincronizzazione sincronizzazione
class Callme { ...
}
class caller implements Runnable { String msg;
Callme target;
public caller(Callme t, String s)
{ target = t; msg = s; new Thread(this).start(); } public void run()
{ synchronized (target) { target.call(msg); } } }
class Synch {
public static void main(String args[]) { Callme target = new Callme();
new caller(target, "Hello");
new caller(target, "Synchronized");
new caller(target, "World");
} }
[Hello]
[Synchronized]
[World] Ingegneria del Software: Programmazione ad Oggetti 22
Threads:
Threads: sincronizzazione sincronizzazione
class Q { int n;
synchronized int get()
{ System.out.println ("Got: " + n); return n; } synchronized void put( int n)
{ this.n = n; System.out.println ("Put: " + n); } }
class Producer implements Runnable { Q q;
Producer(Q q)
{ this.q = q; new Thread(this, "Producer").start(); } public void run() {
int i = 0;
while(true) { q.put(i++); } }
}
class Consumer implements Runnable { Q q;
Consumer(Q q)
{ this.q = q; new Thread(this, "Consumer").start(); } public void run() { while(true) { q.get();} } }
Ingegneria del Software: Programmazione ad Oggetti 23
Threads:
Threads: sincronizzazione sincronizzazione
class PC {
public static void main(String args[]) { Q q = new Q();
new Producer(q);
new Consumer(q);
} }
Put: 1 Got: 1 Got: 1 Got: 1 Put: 2 Put: 3 Put: 4 Got: 4 Got: 4 Put: 5 Put: 6 Got: 6
... Ingegneria del Software: Programmazione ad Oggetti 24
Threads Threads wait, notify e
wait, notify e notifyall notifyall
• permettono la comunicazione tra threads
• wait sospende una thread fino a quando non viene risvegliata da notify o notifyall
• notify sveglia la prima thread in attesa
• notifyall sveglia tutte le threads
• sono tutti metodi definiti nella classe Object e
ereditati da tutte le classi
Ingegneria del Software: Programmazione ad Oggetti 25
Threads Threads wait, notify e
wait, notify e notifyall notifyall
• Possono essere usati solo in metodi dichiarati synchronized
• L’uso standard è il seguente:
synchronized void doWhenCondition() { while (!condition ) wait();
// ... Do what needs doing when condition is true ...
}
synchronized void changeCondition() {
// ... change some value used in a condition test ...
notify(); // or notifyall();
}
Ingegneria del Software: Programmazione ad Oggetti 26
Threads Threads wait, notify e
wait, notify e notifyall notifyall
class Q { int n ;
boolean valueSet = false;
synchronized int get() { if (! valueSet)
try { wait(); } catch ( InterruptedException e) {};
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) { if (valueSet )
try { wait(); } catch (InterruptedException e) {};
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
Put: 1 Got: 1 Put: 2 Got: 2 ...