pip12.gif (3117 bytes)

Threads = movimento!

Praticamente tutti i sistemi operativi supportano il multitasking cioè la possibilità di eseguire più compiti allo stesso tempo; per esempio possiamo usare un editore di testi per scrivere una lettera, ascoltare musica dal lettore CD e scaricare posta elettronica da Internet nello stesso tempo. Java fornisce un supporto per la programmazione multithreated. Un programma multithreated contiene due o più parti (o flussi) che possono essere eseguite contemporaneamente, ogni parte è un thread. Il multithreading è una forma di multitasking. I threads sono molto utili nei programmi di animazione (e non solo).

In Java, un thread è un oggetto della classe Thread; per usare un nuovo thread bisogna implementare l'interfaccia Runnable. Quindi se si vuole usare un nuovo thread nell'applet Esempio (nb: ogni programma, ogni applet contiene in partenza un thread (main thread)) bisognerà fare la seguente dichiarazione:

public class Esempio extends Applet implements Runnable {

dopodichè bisogna definire il metodo run(): all'interno di run() si definisce il codice che costituisce il nuovo thread; run() può chiamare altri metodi, utilizzare altre classi e dichiarare variabili come il thread principale (main thread).

Una volta creato il nuovo thread non potrà essere eseguito finchè non viene chiamato il metodo start().

Finalmente stop() ferma il thread.

Un semplice esempio:

Consideriamo il seguente codice

import java.awt.*;
import java.applet.*;

public class Arco extends Applet implements Runnable {

int a = 10;
Color colore;
Thread runner;


//init
public void init() {
setBackground(Color.orange);
colore = new Color(0,0,0);
    }
public void paint (Graphics g) {
    g.setColor(colore);
    g.fillArc(90,70,100,100,0,a);
    }
//start
public void start() {
if(runner == null) {
    runner = new Thread(this);
    runner.start();
    }
}
//run
public void run() {
Thread thisThread = Thread.currentThread();
while(runner == thisThread) {
    if(a < 360) {
    a = a+10;
    repaint();
        }
    else {
    colore = new Color((int)(Math.random()*256),(int)(Math.random()*256),(int)(Math.random()*256));
    repaint();
    a = 10;
    }
try {
    Thread.sleep(10);
} catch(InterruptedException e) { }
}
}
//stop
public void stop() {
if(runner != null) {
    runner = null;
    }
}
}

il cui risultato è:

L'applet riempie un arco da 0 a 10 = a con il colore colore, fa una pausa di 10 milisecondi, poi, se a < 360, a diventa a+10 e l'applet riempie un arco da 0 ad a. Quando a = 360, si cambia colore in modo casuale, a viene reinizializzato al valore a = 10 e si riparte!

Si osserverà un certo lampeggiamento dello schermo, è un problema che risolveremo dopo.

Commento:

Con Thread runner si dichiara un nuovo thread chiamato runner.

Il metodo start():

public void start() {
    if(runner == null) {
    runner = new Thread(this);
    runner.start;
    }
}

Questo metodo fa un'unica cosa: se il thread runner non è attivo (cioè = = null), il metodo ne crea uno e lo fa partire. La parola chiave this indica l'applet come il programma che verrà eseguito nel thread runner.

Il metodo run():

Uno dei metodi della classe Thread, currentThread(), serve a chiamare il thread corrente; abbiamo quindi battezzato il thread corrente chiamandolo thisThread. Le istruzioni di run() sono eseguite all'interno del ciclo while(runner = = thisThread) { }. Il ciclo verrà eseguito finchè i due threads runner e thisThread sono uguali. Siccome all'interno del ciclo non c'è nessuna istruzione in grado di dare valori diversi a runner e thisThread, il metodo girerà indefinitamente (a meno che un evento esterno (chiusura della pagina web) non venga a modifcare uno dei threads).

Il metodo contiene anche un'istruzione try ... catch per gestire un'eventuale errore. L'istruzione Thread.sleep(10); provoca una pausa di 10 milisecondi; catch s'incarica di ogni errore InterruptedException che potrebbe verificarsi durante l'esecuzione di Thread.sleep() (per esempio se il thread fosse interotto durante l'esecuzione di sleep()).

Il metodo stop():

Questo metodo è eseguito ad ogni arresto dell'applet (per esempio quando si cambia pagina web). Nell'istruzione if si confronta runner a null; se runner non è uguale (!=) a null, allora si pone runner = null; altrimenti non si fa nulla (runner è già null, cioè fermo). Quando runner diventa null, runner diventa  diverso da thisThread e questo provoca la fine del ciclo while di run().

avanti02.gif (9574 bytes)fleche_retour.gif (1377 bytes)