Capitolo 12 Thread Lucidi relativi al volume: Java – Guida alla programmazione James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl La storia finora I programmi sono costituiti da singoli flussi di controllo Il flusso di controllo inizia nella prima istruzione del metodo main() e procede istruzione per istruzione fino all'ultima istruzione del metodo main() Il flusso di controllo può essere passato temporaneamente ad altri metodi con le invocazioni, ma il controllo torna a main() dopo il completamento I programmi con flussi di controllo singoli sono detti processi sequenziali Single-threaded Program { Statement 1; Statement 2; ... Statement k; } Sebbene Alt hough t un'istruzione he st at ement s all'interno wit hin a single di un flusso di controllo possa flow of solo cont rol may invoke ot her met hods, invocare metodi, t he next staltri at ement is notl'istruzione execut ed unt il chet he segue non eseguita current st viene at ement complet es finché la prima non è conclusa Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Processi La capacità di eseguire più processi contemporaneamente è una caratteristica importante dei moderni sistemi operativi Un desktop utente potrebbe eseguire un browser, un IDE di programmazione, un lettore di musica e un sistema di preparazione dei documenti Java supporta la creazione di programmi con flussi di controllo concorrenti, i thread I thread sono eseguiti in un programma e utilizzano le sue risorse per l'esecuzione Processi leggeri Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Processi Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Elaborazione multithread Unit hreaded programma a più A mult program endsthread when allsiof it s conclude quando finiscono tutti individual flows of cont rol (t hreads) endi flussi di controllo individuali (thread) Il programma a più thread This mult it hreaded avvia il thread A per program delegare st art s up t hread A t o assist parte delle operazioni del in t he program's t ask. Aft er programma. Dopo aver st artavviato ing t he tilhread, t he program thread, il cont inues wit h itcontinua s next st atcon ement programma l'istruzione successiva Thread A { A Statement A Statement ... A Statement ... A Statement } Multithread Program { Statement 1; Statement 2; ... Statement i; ... Statement j; ... Statement m; } 1; 2; Thread B { B Statement 1; B Statement 2; n; ... p; Il thread avvia per Thread A A st art s il upthread t hread CCt o delegare operazioni assist parte it in it sdelle program subt ask. del thread. aver thread Aft erDopo st art ing t heavviato t hread, tilhread C, ilAthread A wit continua cont inues h it s nextcon l'istruzione successiva st at ement Il programma più thread This mult it hreadedaprogram also avvia anche il thread B per delegare st art s up t hread B t o assist in t he parte delle operazioni program's t ask. Aft er del st artprogramma. ing t he Dopo aver avviato il thread, t hread, t he program cont inues wit h il programma continua con l'istruzione it s next st at ement successiva B Statement q; } Thread C { C Statement 1; C Statement 2; ... C Statement r; } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Timer e TimerTask Tra le altre, le classi Java java.util.Timer e java.util.TimerTask supportano la creazione e la pianificazione di thread La classe astratta Timer possiede metodi per creare thread dopo un ritardo specificato o in un tempo specifico public void schedule(TimerTask task, long m) Esegue task.run() dopo m millisecondi. public void schedule(TimerTask task, long m, long n) Esegue task.run() dopo m millisecondi. Poi esegue ripetutamente task.run() ogni n millisecondi. public void schedule(TimerTask task, Date y) Esegue task.run() nel momento t. Un thread può essere creato estendendo TimerTask e specificando una definizione per il metodo astratto run() Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Esecuzione dopo un ritardo La classe DisplayCharSequence estende TimerTask per supportare la creazione di un thread che visualizza 20 copie del carattere desiderato (per esempio “H”, “A” o “N”) Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Utilizzo di DisplayCharSequence public static void main(String[] args){ DisplayCharSequence s1 = new DisplayCharSequence('H'); DisplayCharSequence s2 = new DisplayCharSequence('A'); DisplayCharSequence s3 = new DisplayCharSequence('N'); } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Defining DisplayCharSequence import java.util.*; public class DisplayCharSequence extends TimerTask { private char displayChar; Timer timer; public DisplayCharSequence(char c) { displayChar = c; timer = new Timer(); timer.schedule(this, 0); } public void run() { for (int i = 0; i < 20; ++i) { System.out.print(displayChar); } timer.cancel(); } } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Implementazione di un metodo run() Un'implementazione sottoclasse del metodo astratto run() di TimerTask generalmente è divisa in due parti La prima definisce l'azione specifica per l'applicazione che il thread deve eseguire La seconda termina il thread Il thread viene terminato quando viene completata l'azione specifica per l'applicazione // run(): display the occurences of the character of interest public void run() { for (int i = 0; i < 20; ++i) { Desired ion ilt othread be Azioneact che System.out.print(displayChar); performed by t hread deve compiere } Desired actdesiderata ion is L'azione è stata timer.cancel(); complet ed so t hread completata; pertanto, } is canceled il thread viene chiuso Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Esecuzione ripetuta Esempio Aggiornamento di un orologio ad ogni secondo public static void main(String[] args){ SimpleClock clock = new SimpleClock(); } public class SimpleClock extends TimerTask { final static long MILLISECONDS_PER_SECOND = 1000; private JFrame window = new JFrame("Clock"); private Timer timer = new Timer(); private String clockFace = ""; public SimpleClock() { window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setSize(200, 60); Container c = window.getContentPane(); c.setBackground(Color.white); window.setVisible(true); timer.schedule(this, 0, 1*MILLISECONDS_PER_SECOND); } public void run() { Date time = new Date(); Graphics g = window.getContentPane().getGraphics(); g.setColor(Color.WHITE); g.drawString(clockFace, 10, 20); clockFace = time.toString(); g.setColor(Color.BLUE); g.drawString(clockFace, 10, 20); } } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Pianificazione di SimpleClock timer.schedule(this, 0, 1*MILLISECONDS_PER_SECOND); Pausa in millisecondi The millisecond delay prima della prima before t he t hread is esecuzione del firstthread scheduled The numberdiof Numero millisecondi milliseconds bettra ween esecuzioni delt hread thread runs of t he Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Esecuzione all'orario scelto Esempio Pianificazione di calendari a comparsa utilizzando la classe DisplayAlert Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Utilizzo di DisplayAlert public static void main(String[] args){ Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, 9); c.set(Calendar.MINUTE, 30); c.set(Calendar.SECOND, 0); Date studentTime = c.getTime(); c.set(Calendar.HOUR_OF_DAY, 18); c.set(Calendar.MINUTE, 15); c.set(Calendar.SECOND, 0); Date danceTime = c.getTime(); DisplayAlert alert1 = new DisplayAlert( "Prospective student meeting", studentTime); DisplayAlert alert2 = new DisplayAlert( "Dance recital", danceTime); } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Defining DisplayAlert import javax.swing.JOptionPane; import java.awt.*; import java.util.*; public class DisplayAlert extends TimerTask { private String message; private Timer timer; public DisplayAlert(String s, Date t) { message = s + ": " + t; timer = new Timer(); timer.schedule(this, t); } public void run() { JOptionPane.showMessageDialog(null, message); timer.cancel(); } } Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Sleeping I thread possono essere utilizzati per mettere in pausa un programma La classe standard java.lang.Thread possiede un metodo di classe sleep() per mettere in pausa un flusso di controllo public static void sleep(long n) throws InterruptedException Mette in pausa il thread corrente per n millisecondi. Poi lancia una InterruptedException. Java – Guida alla programmazione - James Cohoon, Jack Davidson Copyright © 2004 - The McGraw-Hill Companies srl Esempio di sleeping Codice Date t1 = new Date(); System.out.println(t1); try { Thread.sleep(10000); } catch (InterruptedException e) { } Date t2 = new Date(); System.out.println(t2); Output Fri Jan 31 19:29:45 EST 2003 Fri Jan 31 19:29:55 EST 2003