Sei sulla pagina 1di 6

Thread Java - Introduzione

Primo esempio: il metodo Thread.sleep


Il linguaggio di programmazione Java permette di creare e gestire i thread. A tal proposito, Java fornisce la classe Thread, del package java.lang, che una sottoclasse diretta della superclasse cosmica Object.

O bje ct

T hrea d

Prima di iniziare l'analisi della classe Thread, consideriamo il seguente esempio. Si vuole scrivere un programma che visualizza le stringhe memorizzate in un array, una per volta e a distanza di qualche secondo l'una dall'altra. Il programma molto semplice: dopo aver inizializzato l'array sufficiente inserire in un ciclo for la stampa a video degli elementi dell'array. Per introdurre un ritardo tra una visualizzazione e l'altra, si pu utilizzare il metodo sleep della classe Thread.

public static void sleep(long millis) throws InterruptedException

Sleep un metodo statico, che interrompe il thread per il numero di millisecondi specificato come parametro. Se il thread gi interrotto, il metodo lancia l'eccezione InterruptedException; pertanto, la chiamata a sleep deve essere racchiusa nel costrutto try. Il codice del programma il seguente:
public class SequenzaStringhe { public static void main(String[] args) { String[] stringhe={"stringa 1","stringa 2","stringa 3"}; int indiceCorrente=-1; for(int i=1;i<=9;i++) { indiceCorrente++; if(indiceCorrente==stringhe.length) { indiceCorrente=0; } System.out.println(stringhe[indiceCorrente]);
Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

try { Thread.sleep(4000); } catch(InterruptedException e) { System.out.println("thread interrotto"); } } } }

Questo semplice programma origina un solo thread, che viene sospeso per 4 secondi. Il thread non pu essere interrotto ma solo distrutto, terminando il programma oppure occorre attendere che il ciclo for termini.

Thread di sistema
In Java, esistono un certo numero di thread che vengono avviati dalla virtual machine in modo del tutto trasparente allutente. Tra questi: un thread per la gestione delle interfacce grafiche responsabile della cattura di eventi e dellaggiornamento dei contenuti dellinterfaccia grafica (thread di comunicazione degli eventi); il garbage collection, responsabile di trovare gli oggetti non pi referenziati e quindi eliminabili dallo spazio di memoria dell applicazione; lo stesso metodo main() di una applicazione che viene avviato come un thread (thread principale) sotto il controllo della java virtual machine.

Secondo esempio: thread e swing


Creiamo esempio. un un una versione con interfaccia grafica del programma del precedente La finestra principale contiene: pannello centrale per visualizzare le stringhe; pulsante avvia nell'area sud del frame.

Facendo clic sul pulsante avvia, inizia la visualizzazione delle stringhe.


import import import import import import import import java.awt.BorderLayout; java.awt.Container; java.awt.Graphics; java.awt.event.ActionEvent; java.awt.event.ActionListener; javax.swing.JButton; javax.swing.JFrame; javax.swing.JPanel;

@SuppressWarnings("serial") public class SequenzaStringhe extends JFrame { public static final int LARGHEZZA= 300; public static final int ALTEZZA= 300; private int indiceCorrente=-1; private String stringaCorrente="";
Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

public SequenzaStringhe() { super ("Sequenza di stringhe"); setSize(LARGHEZZA,ALTEZZA); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container contentPane= getContentPane(); JButton avvia= new JButton("avvia"); final Canvas canvas= new Canvas(); contentPane.add(avvia,BorderLayout.SOUTH); contentPane.add(canvas,BorderLayout.CENTER); final String[] stringhe= {"stringa 1","stringa 2","stringa 3"}; avvia.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { for(int i=0;i<9;i++) { indiceCorrente++; System.out.println("indice corrente= "+indiceCorrente); if(indiceCorrente==stringhe.length) { indiceCorrente=0; } stringaCorrente= stringhe[indiceCorrente]; canvas.paint(canvas.getGraphics()); Thread.sleep(4000); } } catch(InterruptedException ecc) { System.err.println("thread interrotto"); } } }); } class Canvas extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); System.out.println("stringa corrente= "+stringaCorrente); g.drawString(stringaCorrente,100,100); } } public static void main(String args[]) { SequenzaStringhe frame= new SequenzaStringhe(); frame.setVisible(true); }

Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

Il programma presenta un problema: quando si fa clic sul pulsante avvia, esso rimane disabilitato fino a quando non termina il ciclo for. Inoltre, l'utente non pu terminare l'applicazione semplicemente chiudendo la finestra, ma deve aspettare che il for termini; l'unico modo per interrompere l'applicazione terminarla brutalmente con una operazione di "kill".

Una possibile soluzione: creare un nuovo thread


Il problema verificatosi nel programma dell'esempio precedente causato dal for contenuto nel gestore dellevento clic su avvia. Infatti, il ciclo for occupa il thread di comunicazione degli eventi, impedendo all'interfaccia di rispondere alle richieste dell'utente. La soluzione consiste nel creare un nuovo thread che svolga l'operazione, indipendentemente dagli altri thread. In generale, si crea un nuovo thread, quando: un'azione richiede molto tempo per essere completata (caso precedente); un'azione pu bloccarsi su un'operazione di I/O. Un modo per creare un nuovo thread quello di definire una sottoclasse della classe Thread. Il codice seguente utilizza un nuovo thread per visualizzare le stringhe in sequenza. Le differenze rispetto al codice precedente sono evidenziate in grassetto.
mport java.awt.BorderLayout; import java.awt.Container; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; @SuppressWarnings("serial") public class SequenzaStringhe extends JFrame { public static final int LARGHEZZA= 300; public static final int ALTEZZA= 300; private private private private int indiceCorrente=-1; String stringaCorrente=""; String[] stringhe= {"stringa 1","stringa 2","stringa 3"}; Canvas canvas;

public SequenzaStringhe() { super ("Sequenza di stringhe"); setSize(LARGHEZZA,ALTEZZA); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container contentPane= getContentPane(); final JButton avvia= new JButton("avvia"); canvas= new Canvas(); contentPane.add(avvia,BorderLayout.SOUTH); contentPane.add(canvas,BorderLayout.CENTER); avvia.addActionListener(new ActionListener() {
Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

public void actionPerformed(ActionEvent e) { StringThread athread= new StringThread(); athread.start(); avvia.setEnabled(false); }); } class Canvas extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); System.out.println("stringa corrente= "+stringaCorrente); g.drawString(stringaCorrente,100,100); } } class StringThread extends Thread { public void run() { try { while(true) { indiceCorrente++; System.out.println("indice corrente= "+indiceCorrente); if(indiceCorrente==stringhe.length) indiceCorrente=0; stringaCorrente= stringhe[indiceCorrente]; canvas.paint(canvas.getGraphics()); Thread.sleep(4000); } } catch(InterruptedException ecc) { System.err.println("thread interrotto"); } } } public static void main(String args[]) { SequenzaStringhe frame= new SequenzaStringhe(); frame.setVisible(true); } }

Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

Il codice del gestore dellevento clic su avvia non contiene pi il ciclo che consente di visualizzare le immagini in sequenza, ma si limita a compiere le seguenti azioni: 1) Crea un'istanza della classe StringThread:
StringThread athread= new StringThread();

Questo equivale a creare un nuovo thread di nome athread. 2) Avvia il thread:


athread.start();

Il metodo start un metodo della classe Thread che causa l'inizio dell'esecuzione del thread ed cos definito:

public void start()

3) Disabilita il pulsante avvia:


avvia.setEnabled(false);

La disabilitazione del pulsante avvia non un'operazione necessaria, ma stata introdotta per evitare di creare pi di un thread aggiuntivo. Infatti, ogni volta che si fa clic sul pulsante avvia, viene creato un nuovo thread. In generale, il gestore di un evento che richiede la creazione di un nuovo thread deve: creare il thread; avviare il thread. La classe StringThread derivata dalla classe Thread e contiene il codice da eseguire in un nuovo thread. Al suo interno ridefinito (overriden) il metodo run della classe Thread (tutte le sottoclassi di Thread devono ridefinire tale metodo), la cui firma :

public void run()

Il metodo run non deve essere invocato esplicitamente dal programmatore poich la sua chiamata avviene mediante il metodo start. Il metodo run del nostro esempio contiene le istruzioni che in precedenza si trovavano nel metodo actionPerformed, con l'unica differenza che il ciclo for stato sostituito da un ciclo while, potenzialmente infinito. Questa sostituzione non necessaria per la gestione dei thread, ma una consuetudine.

Quest'opera stata rilasciata con licenza Creative Commons Attribution-ShareAlike 3.0 Unported. Per leggere una copia della licenza visita il sito web http://creativecommons.org/licenses/by-sa/3.0/ o spedisci una lettera a Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
Autore: Cinzia Bocchi Ultimo aggiornamento: 18/11/2011

Potrebbero piacerti anche