<< Chapter < Page | Chapter >> Page > |
Il codice che segue effettua la lettura periodica di una
linea di testo da un sito generatore di testo. Lo siestenda aggiungendo un thread che visualizza queste frasi
sulla finestra grafica con animazione tipografica.
class sentenceReader extends Thread{
int timediff; // quanto temporalesentenceReader(int td) {timediff = td;
}void run() {while(true) {
try {BufferedReader stdiin = createReader("http://www.essl.at/cgi-bin/swrap/cgis/lexikon-orakel.pl");
for (int i=0; i<13; i++) stdiin.readLine();
println(stdiin.readLine());sleep(timediff);
}catch(Exception e){}}
}}
void setup() {sentenceReader st = new sentenceReader(2000);
st.start();}
void draw() {}
Si supponga di dover estendere la
lettura
di comandi da tastiera con due thread che prendono
comandi da
stdin
. I comandi possono essere
consumati dall'uno o dall'altro dei thread, ma uno stessocomando non può essere consumato da entrambi. In questo caso
si possono presentare problemi di
race
condition , cioè configurazioni di codice concorrente
che danno luogo a risultati dipendenti dalla sequenza di
scheduling attribuita ai vari
thread. In particolare, la
sezione
critica
results=stdin.toString();
stdin.setLength(0);linea = false;
può dare luogo a comportamenti inconsistenti se interrotta
dallo
scheduler per passare il controllo
dall'uno all'altro thread. Questi problemi si possonorisolvere imponendo la non interrompibilità delle sezioni
critiche di codice, per mezzo della parola chiave
synchronized
.
Nella fattispecie, si può introdurre una classe con metodi sincronizzati:
class IO extends Thread {
String results;synchronized String acquire() {
results=stdin.toString();linea = false;
stdin.setLength(0);return(results);
}}
I metodi invocati su un oggetto di questa classe non sono
interrompibili da metodi invocati sullo stesso oggetto. In ambito ditransazioni bancarie, per esempio, un metodo
prelievo()
dovrà essere sincronizzato per evitare inconsistenze in presenza di
prelievi multipli, come possono essere effettuati da co-titolari dellostesso conto. La sincronizzazione di thread è un argomento complesso,
per l'approfondimento del quale esistono
libri
specializzati .
Si estenda la
lettura
di comandi da tastiera con due thread che prendono
comandi da
stdin
.
Nel codice seguente si noti l'uso della
getName()
per stampare il nome del thread
interessato.
StringBuffer stdin;
boolean linea;color colore;
IO io = new IO();void keyReleased() {
char c = key;if (c!='\n') {
stdin.append(c);}
else linea=true;}
class IO extends Thread {String results;
synchronized String acquire() {results=stdin.toString();
linea = false;stdin.setLength(0);
return(results);}
}class ColorInput extends Thread {
String results;char c;void ColorInput (IO inout) {
io = inout;}
void run() {while(true) {
if (linea) {results=io.acquire();
println(this.getName() + results);if (results.equals("rosso")) {
colore = color(255, 0, 0);}
if (results.equals("verde")) {colore = color(0, 255, 0);
}if (results.equals("blu")) {
colore = color(0, 0, 255);}
}try {
sleep(2); // to relief the cpu from active waiting} catch (Exception e) {println("Exception in sleep");}
}}
}class TimerThread extends Thread{
int timediff; // quanto temporaleTimerThread(int td) {timediff = td;
}void run() {while(true) {
try {fill(colore);
ellipse(int(random(100)), int(random(100)),int(random(20)), int(random(20)));
sleep(timediff);} catch (Exception e) {println("Exception in sleep");}
}}
}void setup() {
stdin = new StringBuffer();TimerThread tt1 = new TimerThread(100);
ColorInput ci = new ColorInput();ColorInput ci2 = new ColorInput();
ci.start(); ci2.start();tt1.start();
}void draw() {
}
Il capitolo 9 del libro Visualizing Data -- Ben Fry; O'Really 2007 fornisce esempi di acquisizione asincrona di dati da file e da sitiremoti, con l'utilizzazione di thread e di sincronizzazione.
Notification Switch
Would you like to follow the 'Programmazione di artefatti interattivi' conversation and receive update notifications?