java1 h 16. multithreading. 1. inleiding. threads: delen van het programma die in concurrentie met...

73
JAVA 1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een sequentiële besturingsstroom. Het zijn ‘lichtgewicht’ processen. Java voorziet primitieven voor multithreading. Meeste programmeertalen moeten gebruik maken van OS-primitieven voor multithreading en dus platformspecifieke code gebruiken. De werking van Java’s thread scheduling is wel platform afhankelijk. Een voorbeeld van multithreading is Java’s garbage collector.

Upload: regina-geerts

Post on 08-Jun-2015

214 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 1

H 16. MULTITHREADING. 1. INLEIDING.

Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een sequentiële besturingsstroom.

Het zijn ‘lichtgewicht’ processen. Java voorziet primitieven voor

multithreading. Meeste programmeertalen moeten gebruik

maken van OS-primitieven voor multithreading en dus platformspecifieke code gebruiken.

De werking van Java’s thread scheduling is wel platform afhankelijk.

Een voorbeeld van multithreading is Java’s garbage collector.

Page 2: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 2

2. THREAD TOESTANDEN: LEVENSCYCLUS.

Ready

Running

BlockedSleepingWaiting

start

issue I/O

requestwait

notify

notifyAll

time

ou

t e

xpire

sinterrupt

thread dispatch(assign a processor)

quantum expirationyield

sleep

complete

sleep interval expires

interrupt

Born

enter synchronized

statement

I/O co

mp

lete

sa

cqu

ire lo

ckinterrupt

Bij voltooing van een thread (terugkeer van run methode), wordt de Dead toestand bereikt (hier de final state)

Page 3: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 3

2. THREAD TOESTANDEN: LEVENSCYCLUS.

Thread toestanden. Born state

Thread is juist gecreëerd. Ready state (ook Runnable state)

start method van thread geactiveerd. Thread kan nu in executie.

Running state Thread is toegekend aan processor en in

executie. Dispatching the thread.

Dead state Thread is beëindigd (taak volbracht of exit) Garbage collector kan geheugen terug vrijgeven.

Page 4: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 4

2. THREAD TOESTANDEN: LEVENSCYCLUS.

Blocked state Als een taak niet onmiddellijk kan volbracht

worden (vb. i/o verzoek). Waiting state

Als een deel code nog niet kan uitgevoerd worden (bepaalde vereisten moeten voldaan zijn) thread activeerd Object’s wait methode.

Sleeping state Thread wacht tot slaaptijd is verstreken.

Page 5: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 5

3. THREAD PRIORITIES EN SCHEDULING.

Priority: indicatie van belangrijkheid (voorrang voor processortijd).

Thread.MIN_PRIORITY (0) .. Thread.NORM_PRIORITY (5) .. Thread.MAX_PRIORITY (10).

Thread scheduler: zorgt ervoor dat de thread met hoogste prioriteit in Running state verkeert. Bij meerdere threads met gelijke prioriteit wordt timeslicing gebruikt. Elke thread krijgt een ‘quantum’ processortijd toegewezen.

Niet elk Java platform ondersteund timeslicing. De Thread methode yield kan er dan voor zorgen dat threads van gelijke prioiteit kunnen concurreren.

Page 6: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 6

3. THREAD PRIORITIES EN SCHEDULING.

Priority 9

Priority 8

Priority 7

Priority 10

Priority 6

Priority 5

Priority 4

Priority 3

Priority 2

Priority 1

A B

D

C

E F

G

H I

J K

Ready threads

Thread.MIN_PRIORITY

Thread.MAX_PRIORITY

Thread.NORM_PRIORITY

Page 7: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 7

4. CREATIE EN EXECUTIE VAN THREADS.

Demonstratie van sleep methode. Creatie van 3 threads met default prioriteit die op willekeurig tijdsinterval een bericht tonen.

// class PrintThread bestuurt de thread executieclass PrintThread extends Thread { private int sleepTime; public PrintThread( String name ) { // geef de thread een naam

super( name ); // kies een willekeurige slaaptijd tussen 0 and 5 seconde

sleepTime = ( int ) ( Math.random() * 5001 ); }

Page 8: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 8

// method run wordt automatisch geactiveerd bij een nieuwe thread public void run() { // breng thread in sleep toestand voor sleepTime seconde try { System.err.println( getName() + " going to sleep for " + sleepTime ); Thread.sleep( sleepTime ); } // als de thread gedurende de sleep toestand wordt onderbroken, print stack trace catch ( InterruptedException exception ) { exception.printStackTrace(); } // print thread name System.err.println( getName() + " done sleeping" ); } } // einde class PrintThread

4. CREATIE EN EXECUTIE VAN THREADS.

Page 9: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 9

4. CREATIE EN EXECUTIE VAN THREADS.

// Meerdere threads die op verschillende tijdsintervallen printen.

public class ThreadTester

{ public static void main( String [] args )

{ // creatie van de drie threads

PrintThread thread1 = new PrintThread( "thread1" ); //thread1 in Born toestand

PrintThread thread2 = new PrintThread( "thread2" ); //thread1 in Born toestand

PrintThread thread3 = new PrintThread( "thread3" ); //thread1 in Born toestand

System.err.println( "Starting threads" );

thread1.start(); // Plaats thread1 in Ready toestand

thread2.start(); // Plaats thread2 in Ready toestand

thread3.start(); // Plaats thread3 in Ready toestand

System.err.println( "Threads started, main ends\n" );

}

}

Page 10: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 10

4. CREATIE EN EXECUTIE VAN THREADS.

Als een thread voor de eerste keer in de Running toestand komt wordt de methode run geactiveerd.

Ook al is de maincode beëindigd, het programma eindigt pas als alle threads de Dead toestand bereikt hebben.

Starting threadsThreads started, main ends thread1 going to sleep for 1217thread2 going to sleep for 3989thread3 going to sleep for 662thread3 done sleepingthread1 done sleepingthread2 done sleeping

Starting threadsthread1 going to sleep for 314thread2 going to sleep for 1990Threads started, main ends thread3 going to sleep for 3016thread1 done sleepingthread2 done sleepingthread3 done sleeping

Page 11: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 11

5. THREAD SYNCHRONISATIE.

Meerdere threads kunnen een object delen, ‘shared object’. Wanneer meerdere threads het shared object kunnen

wijzigen kunnen er problemen ontstaan. mutual exclusion of thread synchronisatie. in Java gebruik van monitors voor synchronisatie.

Elk object heeft een monitor: geeft maar één thread tegelijkertijd executierecht bij een synchronized statement op het object, ‘obtaining the lock’. Andere threads komen in Blocked toestand. Als de lock wordt vrijgegeven, ‘released’, zal de monitor de geblokte thread met hoogste priority laten voortgaan.

Een volledige methode kan synchronized zijn. Deadlock preventie: als een thread de wait methode

activeert, zorg dan dat een afzonderlijke thread de notify methode activeerd voor overgang naar de Ready toestand.

Page 12: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 12

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

Producer: genereert data en bewaart het in een shared object.

Consumer: leest de data van het shared object. In multithreaded applicatie:

Componenten: producerthread, consumerthread en buffer.

Producerthread:

Activeer wait: als vorige data nog niet verwerkt is,

consumer kan data ophalen.

Activeer notify: als nieuwe data in buffer geplaatst is. Consumerthread:

Activeer notify: als de data opgehaald is, producer kan

nieuwe data in buffer plaatsen.

Activeer wait: als buffer leeg is of vorige data nog

aanwezig is.

Page 13: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 13

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

Mogelijke logische fouten als we geen synchronisatie gebruiken: VOORBEELD SharedBufferTest.

Producer genereert een reeks getallen van 1 tot 4. Consumer telt het aantal getallen en sommeert die getallen. Bij beide threads is een random vertraging ingebouwd (0 tot 3 seconden sleep) om een reëel programma te simuleren. Bij multithreaded applicaties is het ongekend wanneer een thread zijn taak uitvoert en hoelang dat duurt.

Beide threads drukken ook de getallen af.  Componenten: Interface Buffer en Klassen Producer,

Consumer, UnsynchronizedBuffer en SharedBufferTest.

Page 14: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 14

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public interface Buffer

{ public void set( int value ); // plaats een waarde in de buffer

public int get(); // haal een waarde uit de buffer

}

public class Producer extends Thread

{ private Buffer sharedLocation; // reference naar shared object

public Producer( Buffer shared )

{ super( "Producer" );

sharedLocation = shared;

}

Page 15: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 15

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public void run() // berg waarden 1 tot 4 op in sharedLocation

{ for ( int count = 1; count <= 4; count++ )

{ try

{ // sleep 0 to 3 seconde en plaats waarde in buffer

Thread.sleep( ( int ) ( Math.random() * 3001 ) );

sharedLocation.set( count );

}

// indien sleeping thread interrupted druk stack trace

catch ( InterruptedException exception )

{ exception.printStackTrace();

}

}

System.err.println( getName() + " done producing." + "\nTerminating " + getName() + ".");

}

} // einde class Producer

Page 16: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 16

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public class Consumer extends Thread

{ private Buffer sharedLocation; // reference naar shared object

public Consumer( Buffer shared )

{ super( "Consumer" );

sharedLocation = shared;

}

Page 17: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 17

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public void run() // lees sharedLocation's waarde 4 keer en sommeer de waarden

{ int sum = 0;

for ( int count = 1; count <= 4; count++ )

{ try // sleep 0 to 3 seconden en lees waarde uit de buffer en tel bij som

{ Thread.sleep( ( int ) ( Math.random() * 3001 ) );

sum += sharedLocation.get();

}

// indien sleeping thread interrupted druk stack trace

catch ( InterruptedException exception )

{ exception.printStackTrace();

}

}

System.err.println( getName() + " read values totaling: " + sum +

".\nTerminating " + getName() + ".");

} } // einde class Consumer

Page 18: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 18

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public class UnsynchronizedBuffer implements Buffer

{ private int buffer = -1; // gedeeld door producer en consumer threads

// plaats waarde in buffer

public void set( int value )

{ System.err.println( Thread.currentThread().getName() + " writes " + value );

buffer = value;

}

// return waarde uit buffer

public int get()

{ System.err.println( Thread.currentThread().getName() + " reads " + buffer );

return buffer;

}

}

Page 19: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 19

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

public class SharedBufferTest

{ public static void main( String [] args )

{ // instantiatie van het shared object gebruikt door de threads

Buffer sharedLocation = new UnsynchronizedBuffer(); // instantiatie van producer and consumer objecten Producer producer = new Producer( sharedLocation );

Consumer consumer = new Consumer( sharedLocation );

producer.start(); // start producer thread

consumer.start(); // start consumer thread

}

}

Page 20: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 20

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

 Consumer reads -1Producer writes 1Consumer reads 1Consumer reads 1Consumer reads 1Consumer read values totaling: 2.Terminating Consumer.Producer writes 2Producer writes 3Producer writes 4Producer done producing.Terminating Producer.

 Producer writes 1Producer writes 2Consumer reads 2Producer writes 3Consumer reads 3Producer writes 4Producer done producing.Terminating Producer.Consumer reads 4Consumer reads 4Consumer read values totaling: 13.Terminating Consumer.

Page 21: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 21

6. PRODUCER/CONSUMER RELATIE ZONDER SYNCHRONISATIE.

Producer writes 1Consumer reads 1Producer writes 2Consumer reads 2Producer writes 3Consumer reads 3Producer writes 4Producer done producing.Terminating Producer.Consumer reads 4Consumer read values totaling: 10.Terminating Consumer.

Page 22: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 22

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE.

Uit vorige voorbeeld blijkt synchronisatie noodzakelijk. Threads die toegang nemen tot een shared object merken zelf

niets van de synchronisatie. Synchronisatiecode komt in de set en get methoden van SynchronizedBuffer.

Er wordt een extra attribuut gebruikt: int occupiedBufferCount. Dit is een ‘condition’ variabele. Hiermee wordt de communicatie geregeld, mag de buffer gevuld/geledigd worden?

Het activeren van de wait methode brengt de thread in Wait toestand waardoor de blokkering voor het gesynchroniseert object beëindigd wordt (release lock).

public class SynchronizedBuffer implements Buffer

{ private int buffer = -1; // // gedeeld door producer en consumer threads

private int occupiedBufferCount = 0; // geeft aantal bezette buffers

Page 23: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 23

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE.

public synchronized void set( int value ) // plaats waarde in buffer

{ String name = Thread.currentThread().getName(); // voor afdrukken status thread

while ( occupiedBufferCount == 1 ) // zolang buffer niet leeg, plaats thread in Wait toestand

{ try // afdrukken thread en buffer status

{ System.err.println( name + " tries to write." );

displayState( "Buffer full. " + name + " waits." );

wait();

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

buffer = value; // plaats nieuwe waarde in buffer

++occupiedBufferCount; // registreer dat buffer gevuld is… consumer moet buffer ledigen

displayState( name + " writes " + buffer );

notify(); // verwittig de thread in Wait toestand om naar Ready toestand over te gaan

} // einde methode set; beëindig blokkering op SynchronizedBuffer (release lock)

Page 24: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 24

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE.

public synchronized int get() // levert waarde uit buffer

{ String name = Thread.currentThread().getName();

while ( occupiedBufferCount == 0 ) // zolang buffer leeg, plaats thread in Wait toestand

{ try // afdrukken thread en buffer status

{ System.err.println( name + " tries to read." );

displayState( "Buffer empty. " + name + " waits." );

wait();

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

--occupiedBufferCount; // registreer dat buffer leeg is… producer moet buffer vulllen

displayState( name + " reads " + buffer );

notify(); // verwittig de thread in Wait toestand om naar Ready toestand over te gaan

return buffer ;

} // einde methode get; beëindig blokkering op SynchronizedBuffer (release lock)

Page 25: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 25

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE.

// toon huidige operatie en buffer status

public void displayState( String operation )

{ StringBuffer outputLine = new StringBuffer( operation );

outputLine.setLength( 40 );

outputLine.append( buffer + "\t\t" + occupiedBufferCount );

System.err.println( outputLine );

System.err.println();

}

} // einde class SynchronizedBuffer

• Zonder notify blijft de andere thread in Waiting toestand en veroorzaakt deadlock.

• Indien met meer dan 2 threads: gebruik notifyAll.

Page 26: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 26

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE.

public class SharedBufferTest2

{ public static void main( String [] args )

{ SynchronizedBuffer sharedLocation = new SynchronizedBuffer();

StringBuffer columnHeads = new StringBuffer( "Operation" );

columnHeads.setLength( 40 ); columnHeads.append( "Buffer\t\tOccupied Count" );

System.err.println( columnHeads ); System.err.println();

sharedLocation.displayState( "Initial State" );

// instantiatie van producer and consumer objecten

Producer producer = new Producer( sharedLocation );

Consumer consumer = new Consumer( sharedLocation );

producer.start(); // start producer thread

consumer.start(); // start consumer thread

}

}

Page 27: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 27

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE. Output 1.

Operation Buffer Occupied Count

 

Initial State -1 0

 

Consumer tries to read.

Buffer empty. Consumer waits. -1 0 Producer writes 1 1 1 Consumer reads 1 1 0 Consumer tries to read.Buffer empty. Consumer waits. 1 0 Producer writes 2 2 1 Consumer reads 2 2 0

Producer writes 3 3 1

Page 28: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 28

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE. Output 1.

Consumer reads 3 3 0 Consumer tries to read.Buffer empty. Consumer waits. 3 0 Producer writes 4 4 1 Consumer reads 4 4 0Producer done producing.Terminating Producer. Consumer read values totaling: 10.Terminating Consumer.

Vervolg…

Page 29: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 29

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE. Output 2.Operation Buffer Occupied Count Initial State -1 0 Consumer tries to read.Buffer empty. Consumer waits. -1 0 Producer writes 1 1 1 Consumer reads 1 1 0 

Producer writes 2 2 1 Producer tries to write.Buffer full. Producer waits. 2 1 Consumer reads 2 2 0 Producer writes 3 3 1 Consumer reads 3 3 0

Producer writes 4 4 1

Page 30: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 30

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE. Output 2.

Producer done producing.Terminating Producer.Consumer reads 4 4 0 Consumer read values totaling: 10.Terminating Consumer.

Vervolg…

Page 31: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 31

7. PRODUCER/CONSUMER RELATIE MET SYNCHRONISATIE. Output 3.Operation Buffer Occupied Count Initial State -1 0 Producer writes 1 1 1 Consumer reads 1 1 0 Producer writes 2 2 1Consumer reads 2 2 0 Producer writes 3 3 1 Consumer reads 3 3 0 Producer writes 4 4 1 Producer done producing.Terminating Producer.Consumer reads 4 4 0 Consumer read values totaling: 10.Terminating Consumer.

Page 32: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 32

OEFENING SYNCHRONISATIE: RESTAURANT

Simuleer de werking in een restaurant: er is één kok die orders klaarmaakt en er zijn twee kelners (Sofie en Hendrik) die de orders naar de klant brengen. Stel een random vertraging in van 0 tot 2 seconden bij de kok en de kelners.

Na 10 orders sluit het restaurant (voedsel is op).

Page 33: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 33

OEFENING SYNCHRONISATIE: RESTAURANT

Gebruik onderstaande klasse voor de orders:

class Order

{ private static int i = 1;

private int count = i++;

public Order()

{ if (count > 10)

{ System.out.println("Voedsel is op, sluiten!");

System.exit(0);

}

}

public String toString()

{ return "Order " + count;

}

}

Page 34: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 34

class Kelner extends Thread

{ private Restaurant restaurant; private String naam;

public Kelner(Restaurant r, String n)

{ restaurant = r; naam = n;

start();

}

public void run()

{ while(true)

{ try

{ sleep((int) (Math.random()*2001));

}

catch(InterruptedException e) { throw new RuntimeException(e); }

Order order = restaurant.getOrder();

System.out.println("Kelner " + naam + " krijgt " + order);

}

}

}

OPLOSSING SYNCHRONISATIE: RESTAURANT

Page 35: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 35

class Kok extends Thread

{ private Restaurant restaurant;

public Kok(Restaurant r)

{ restaurant = r;

start();

}

public void run()

{ while(true)

{ try

{ sleep((int) (Math.random()*2001));

restaurant.setOrder(new Order());

}

catch(InterruptedException e) { throw new RuntimeException(e); }

}

}

}

OPLOSSING SYNCHRONISATIE: RESTAURANT

Page 36: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 36

public class Restaurant

{ private Order order;

public synchronized void setOrder(Order o)

{ while (order!=null)

try

{ wait();

}

catch(InterruptedException e) { throw new RuntimeException(e); }

order=o;

notifyAll();

}

OPLOSSING SYNCHRONISATIE: RESTAURANT

Page 37: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 37

public synchronized Order getOrder()

{ while (order==null)

{ try

{ wait();

}

catch(InterruptedException e) { throw new RuntimeException(e); }

}

Order ref=order;

order = null;

notifyAll();

return ref;

}

OPLOSSING SYNCHRONISATIE: RESTAURANT

Page 38: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 38

public static void main(String[] args)

{ Restaurant restaurant = new Restaurant();

new Kelner(restaurant, "Sofie");

new Kelner(restaurant, "Hendrik");

new Kok(restaurant);

}

}

OPLOSSING SYNCHRONISATIE: RESTAURANT

Page 39: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 39

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Synchronisatie zoals in vorig punt kan tot inefficiëntie leiden, er kan veel tijd verloren gaan in de Wait toestand.

Als de producer sneller is, moet die steeds wachten op de consumer om de volgende waarde te kunnen leveren.

Als de consumer sneller is, moet die steeds wachten op de producer die de waarde levert.

Zelfs als ze ongeveer even snel zijn zullen ze op elkaar moeten wachten omdat ze ‘tegenover elkaar verlopen’.

We voorzien extra buffer ruimte : een circulaire buffer. De circulaire buffer is enkel wanneer beide threads

ongeveer even snel zijn. De juiste grootte van de buffer is cruciaal om de thread-wait tijd te minimaliseren.

Het voorbeeld gebruikt een circulaire buffer van 3 elementen en werkt met Swing componenten. Swing componenten zijn niet thread-safe. Daarom gebruiken we een event-dispatching thread.

Page 40: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 40

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Alle interactie met swingGUIcomponenten mag niet door meerdere threads ‘tegelijkertijd’ gebeuren.

De swing klasse SwingUtilities voorziet de statische methode invokeLater. Het argument moet een object zijn dat de interface Runnable (package java.lang) implementeert. Runnable heeft als enige methode void run(). Ieder thread is een Runnable object.

invokeLater zal GUI verwerkende opdrachten laten uitvoeren als deel van de event-dispatching thread. De uitvoering gebeurt nadat alle in verzoek zijnde (‘pending’) AWT events zijn verwerkt. invokeLater is asynchroon, wacht niet tot de opdracht is uitgevoerd. invokeAndWait is synchroon, opgelet voor deadlock.

Page 41: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 41

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class RunnableOutput.

import javax.swing.*;

public class RunnableOutput implements Runnable

{ private JTextArea outputArea;

private String messageToAppend;

public RunnableOutput( JTextArea output, String message )

{ outputArea = output; // een referentie naar de JTextArea waar de output naar toe moet

messageToAppend = message; // de boodschap die in JTextArea moet toegevoegd worden

}

public void run() // wordt door SwingUtilities.invokeLater gebruikt voor activatie

{ outputArea.append( messageToAppend );

}

}

Page 42: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 42

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class Producer.

// Producer’s run methode is een thread die de waarden 11 tot 20 opslaat in sharedLocation.

import javax.swing.*;

public class Producer extends Thread

{ private Buffer sharedLocation; // reference naar shared object

private JTextArea outputArea;

public Producer( Buffer shared, JTextArea output )

{ super( "Producer" );

sharedLocation = shared;

outputArea = output;

}

Page 43: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 43

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class Producer.

public void run()

{ for ( int count = 11; count <= 20; count ++ )

{ try // sleep 0 tot 3 seconde voordat de waarde in Buffer wordt geplaatst

{ Thread.sleep( ( int ) ( Math.random() * 3000 ) );

sharedLocation.set( count );

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

String name = getName();

SwingUtilities.invokeLater( new RunnableOutput( outputArea, "\n" +

name + " done producing.\n" + name + " terminated.\n" ) );

} // einde methode run

} // einde class Producer

Page 44: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 44

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class Consumer.

// Consumer’s run methode is een thread die 10 maal een waarde ophaalt uit sharedLocation.

import javax.swing.*;

public class Consumer extends Thread

{ private Buffer sharedLocation; // reference naar shared object

private JTextArea outputArea;

public Consumer( Buffer shared, JTextArea output )

{ super( "Consumer" );

sharedLocation = shared;

outputArea = output;

}

Page 45: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 45

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class Consumer.

public void run()

{ int sum = 0;

for ( int count = 1; count <= 10; count++ )

{ try // sleep 0 tot 3 seconde voordat de waarde uit Buffer wordt gelezen en gesommeerd

{ Thread.sleep( ( int ) ( Math.random() * 3001 ) );

sum += sharedLocation.get();

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

String name = getName();

SwingUtilities.invokeLater( new RunnableOutput( outputArea,

"\nTotal " + name + " consumed: " + sum + ".\n" +

name + " terminated.\n ") );

}

} // einde class Consumer

Page 46: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 46

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

// CircularBuffer synchroniseert toegang tot een array van shared buffers.

import javax.swing.*;

public class CircularBuffer implements Buffer

{ private int buffers[] = { -1, -1, -1 }; // elk array element is een buffer

private int occupiedBufferCount = 0;

private int readLocation = 0, writeLocation = 0; // onderhouden de lees/schrijf positie in de array

private JTextArea outputArea; // reference naar GUI component voor output

public CircularBuffer( JTextArea output )

{ outputArea = output;

}

Page 47: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 47

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

public synchronized void set( int value ) // plaats waarde in buffer

{ String name = Thread.currentThread().getName();

while ( occupiedBufferCount == buffers.length ) // zolang er geen plaats

{ try // afdrukken thread en buffer status, plaats thread in Wait toestand

{ SwingUtilities.invokeLater( new RunnableOutput( outputArea,

"\nAll buffers full. " + name + " waits." ) );

wait();

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

Page 48: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 48

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

buffers[ writeLocation ] = value; // plaats waarde op writeLocation in buffers

SwingUtilities.invokeLater( new RunnableOutput( outputArea, // update Swing GUI component

"\n" + name + " writes " + buffers[ writeLocation ] + " ") );

++occupiedBufferCount; // en verhoog het aantal bezette buffers

writeLocation = ( writeLocation + 1 ) % buffers.length; // update voor toekomstige schrijfoperatie

SwingUtilities.invokeLater( new RunnableOutput( // toon de inhoud van de shared buffers

outputArea, createStateOutput() ) );

notify(); // breng waiting thread (als er een is) terug naar ready toestand

} // einde methode set

Page 49: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 49

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

public synchronized int get() // levert waarde uit buffer

{ String name = Thread.currentThread().getName();

// while no data to read, place thread in waiting state

{ try // afdrukken thread en buffer status, plaats thread in Wait toestand

{ SwingUtilities.invokeLater( new RunnableOutput( outputArea,

"\nAll buffers empty. " + name + " waits.") );

wait();

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

}

Page 50: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 50

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

int readValue = buffers[ readLocation ]; // haal waarde op readLocation uit buffers

SwingUtilities.invokeLater( new RunnableOutput( outputArea, // update Swing GUI component

"\n" + name + " reads " + readValue + " ") );

--occupiedBufferCount; // er is een buffer vrijgekomen

readLocation = ( readLocation + 1 ) % buffers.length; // update voor toekomstige leesoperatie

SwingUtilities.invokeLater( new RunnableOutput( // toon de inhoud van de shared buffers

outputArea, createStateOutput() ) );

notify(); // breng waiting thread (als er een is) terug naar ready toestand

return readValue;

} // einde methode get

Page 51: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 51

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

public String createStateOutput()

{ // eerste lijn status informatie

String output = "(buffers occupied: " + occupiedBufferCount + ")\nbuffers: ";

for ( int i = 0; i < buffers.length; i++ )

output += " " + buffers[ i ] + " ";

// tweede lijn status informatie

output += "\n ";

for ( int i = 0; i < buffers.length; i++ )

output += "---- ";

// derde lijn status informatie

output += "\n “;

Page 52: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 52

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBuffer.

// plaats indicators R(readLocation) en W (writeLocation)

// onder de betreffende buffer locaties

for ( int i = 0; i < buffers.length; i++ )

if ( i == writeLocation && writeLocation == readLocation )

output += " WR ";

else if ( i == writeLocation )

output += " W ";

else if ( i == readLocation )

output += " R ";

else

output += " ";

output += "\n";

return output;

} // einde methode createStateOutput

} // einde class CircularBuffer

Page 53: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 53

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBufferTest.

// CircularBufferTest toont twee threads die gebruik maken van een circulaire buffer.

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

// creatie en activatie van de producer en consumer threads

public class CircularBufferTest extends JFrame

{ JTextArea outputArea;

// opbouw GUI

public CircularBufferTest()

{ super( "Demonstrating Thread Synchronizaton" );

outputArea = new JTextArea( 20,30 );

outputArea.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) );

getContentPane().add( new JScrollPane( outputArea ) );

setSize( 310, 500 );

setVisible( true );

Page 54: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 54

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER. Class CircularBufferTest.

// creatie van het shared object CircularBuffer dat gedeeld zal worden door beide threads CircularBuffer sharedLocation = new CircularBuffer( outputArea ); // afdrukken van de initiële status van de buffers in CircularBuffer SwingUtilities.invokeLater( new RunnableOutput( outputArea, sharedLocation.createStateOutput() ) ); // creatie van de producer en consumer threads

Producer producer = new Producer( sharedLocation, outputArea ); Consumer consumer = new Consumer( sharedLocation, outputArea ); producer.start(); // start producer thread consumer.start(); // start consumer thread } // einde constructor public static void main ( String args[] ) { CircularBufferTest application = new CircularBufferTest(); application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); }} // einde class CirclularBufferTest

Page 55: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 55

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Waarde in laatste buffer geplaatst. De volgende waarde komt in de eerste buffer.

Page 56: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 56

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Circulair buffer effect—de vierde waarde wordt in de eerste buffer geplaatst.

Waarde in laatste buffer geplaatst. De volgende waarde komt in de eerste buffer.

Circulair buffer effect—de zevende waarde wordt in de eerste buffer geplaatst.

Page 57: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 57

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Waarde in laatste buffer geplaatst. De volgende waarde komt in de eerste buffer.

Circulair buffer effect—de tiende waarde wordt in de eerste buffer geplaatst.

Page 58: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 58

8. PRODUCER/CONSUMER RELATIE: CIRCULAIRE BUFFER.

Page 59: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 59

9. DEAMON THREADS.

Een thread die als ondersteuning van andere threads meedraait. De deamon thread verhindert niet dat een programma beëindigd wordt.

Java’s garbage collector is een voorbeeld van een deamon thread.

We markeren een thread als deamon met de methode setDeamon(true). Dit moet wel gebeuren voordat de start methode van de thread geactiveerd wordt.

Page 60: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 60

10. RUNNABLE INTERFACE.

Een klasse die al subklasse is kan niet meer erven van Thread; er is geen meervoudige overerving in Java toegelaten. Dergelijke klasse kan wel de interface Runnable implementeren (zoals overigens ook klasse Thread doet).

De klasse thread voorziet vijf constructors met een Runnable object als argument.

public Thread(Runnable runnableObject) public Thread(Runnable runnableObject, String threadName)

VOORBEELD: een applet met twee innerklassen die de interface Runnable implementeren.

Eén voor beheer van threads aangemaakt in de applet. Eén voor GUI updates. Codeertechnieken voor suspend, resume en stop worden

geïllustreerd (afgekeurde methoden van Thread). Door thread synchronisatie en Objects methode wait en notify.

Page 61: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 61

10. RUNNABLE INTERFACE.

Page 62: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 62

10. RUNNABLE INTERFACE.

// Class RandomCharacters demonstreert the Runnable interface

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class RandomCharacters extends JApplet implements ActionListener

{ private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private final static int SIZE = 3;

private JLabel outputs[];

private JCheckBox checkboxes[];

private Thread threads[];

private boolean suspended[];

Page 63: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 63

10. RUNNABLE INTERFACE. public void init() //aanmaak GUI en arrays

{ outputs = new JLabel[ SIZE ]; checkboxes = new JCheckBox[ SIZE ];

threads = new Thread[ SIZE ]; suspended = new boolean[ SIZE ];

Container container = getContentPane();

container.setLayout( new GridLayout( SIZE, 2, 5, 5 ) );

for ( int count = 0; count < SIZE; count++ )

{ outputs[ count ] = new JLabel();

outputs[ count ].setBackground( Color.GREEN );

outputs[ count ].setOpaque( true );

container.add( outputs[ count ] );

checkboxes[ count ] = new JCheckBox( "Suspended" );

checkboxes[ count ].addActionListener( this );

container.add( checkboxes[ count ] );

}

} // end method init

Page 64: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 64

10. RUNNABLE INTERFACE.

public void start() // creatie en start threads telkens start methode van de Applet wordt geactiveerd

{ for ( int count = 0; count < threads.length; count++ )

{ // create Thread; initialize object that implements Runnable

threads[ count ] = new Thread( new RunnableObject(), "Thread " + ( count + 1 ) );

threads[ count ].start(); // begin executing Thread

}

}

private int getIndex( Thread current ) // bepaal thread locatie in threads array

{ for ( int count = 0; count < threads.length; count++ )

if ( current == threads[ count ] )

return count;

return -1;

}

Page 65: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 65

10. RUNNABLE INTERFACE. public synchronized void stop() // stop alle threads als stop methode van de Applet wordt geactiveerd

{ for ( int count = 0; count < threads.length; count++ )

threads[ count ] = null; // zet references op null zodat de threads run methode te beëindigt

notifyAll(); // notify all waiting threads, so they can terminate

}

public synchronized void actionPerformed( ActionEvent event ) //verwerk button events

{ for ( int count = 0; count < checkboxes.length; count++ )

{ if ( event.getSource() == checkboxes[ count ] )

{ suspended[ count ] = !suspended[ count ]; //verander labelkleur bij suspend/resume

outputs[ count ].setBackground( suspended[ count ] ? Color.RED : Color.GREEN );

if ( !suspended[ count ] ) //bij resume: verzeker dat de thread tot executie overgaat

notifyAll();

return;

}

}

}

Page 66: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 66

10. RUNNABLE INTERFACE. private class RunnableObject implements Runnable // inner klasse om de threads te besturen

{ public void run() // plaats willekeurig letters in GUI label

{ final Thread currentThread = Thread.currentThread(); //moeten final omdat inner class

final int index = getIndex( currentThread ); // ernaar refereert

while ( threads[ index ] == currentThread ) //deze voorwaarde kan de thread doen beëindigen

{ try //dit gebeurt door thread[index] op null te zetten

{ Thread.sleep( ( int ) ( Math.random() * 1000 ) ); // sleep 0 tot 1 seconde

// determine whether thread should suspend execution;

synchronized( RandomCharacters.this ) //moet execution suspend worden

{ while ( suspended[ index ] && threads[ index ] == currentThread )

{ RandomCharacters.this.wait(); // tijdelijk suspend thread executie

}

} // einde synchronized block

}

catch ( InterruptedException exception ) { exception.printStackTrace(); }

Page 67: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 67

10. RUNNABLE INTERFACE.

SwingUtilities.invokeLater( new Runnable()

{ public void run() //kies willekeurig een character en toon in JLabel

{ char displayChar = alphabet.charAt( ( int ) ( Math.random() * 26 ) );

outputs[ index ].setText( currentThread.getName() + ": " + displayChar );

}

} ); // einde anonieme inner class

} // einde while methode run

System.err.println( currentThread.getName() + " terminating" );

} // einde method run

} // einde private inner class RunnableObject

} // einde class RandomCharacters

Page 68: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 68

Oefening: Responsible GUI.

Schrijf een GUI applicatie die de interactiviteit met de gebruiker blijft verzorgen. Na het activeren van een taak zal niet gewacht worden tot die eventeel tijdslopende taak voltooid is. De applicatie kan onmiddellijk nieuwe verzoeken van de gebruiker accepteren.

Voorzie een JFrame met drie Jbuttons (taak1, taak2, taak3) die een taak activeren. Je kiest voor willekeurige slaaptijd van 0 tot 10 seconden om ‘het werk’ te simuleren.Een taak informeert steeds in het JTextArea dat ze gestart is “Taak1 gestart”. Wanneer de taak gaat eindigen zal ze de regel verder aanpassen door de uitbreiding “... volbracht”.

Page 69: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 69

Oefening:ResponsibleGUI.

Page 70: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 70

OPLOSSING RESPONSIBLE GUI.import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

class ResponsiveGUI extends JFrame

{ private JButton btnTask1, btnTask2, btnTask3;

private JTextArea edOut;

private ActionListener buttonHandler;

public ResponsiveGUI()

{ super("Responsive GUI");

edOut = new JTextArea(10, 20); edOut.setEditable(false);

buttonHandler = new ActionListener()

{ public void actionPerformed(ActionEvent e)

{ if (e.getSource()==btnTask1) { new Task1(edOut).start(); }

// enz … tot btnTaskn

}

};

Page 71: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 71

OPLOSSING RESPONSIBLE GUI.

btnTask1 = new JButton("Taak1");

// enz tot btnTaskn

btnTask1.addActionListener(buttonHandler);

// enz tot btnTaskn

Container c = getContentPane(); c.setLayout(new FlowLayout());

c.add(btnTask1);

// enz tot btnTaskn

c.add(new JScrollPane(edOut));

}

Page 72: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 72

public static void main(String arg[]) { ResponsiveGUI rpGUI = new ResponsiveGUI(); rpGUI.setSize(300,100); rpGUI.setVisible(true); rpGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }}class UpdateMessage implements Runnable{ String mes; JTextArea edOut; public UpdateMessage(String m, JTextArea t) { mes=m; edOut = t; } public void run() { StringBuffer buf = new StringBuffer(edOut.getText()); int i = buf.indexOf(mes); edOut.setText(buf.replace(i+mes.length()-1, i+mes.length(),"... volbracht\n").toString()); }}

OPLOSSING RESPONSIBLE GUI.

Page 73: JAVA1 H 16. MULTITHREADING. 1. INLEIDING. Threads: delen van het programma die in concurrentie met elkaar gelijktijdig in executie gaan. Thread is een

JAVA 73

OPLOSSING RESPONSIBLE GUI.

class Task1 extends Thread{ JTextArea edOut; public Task1(JTextArea f) { edOut = f; } public void run() { String mes = "Taak1 gestart\n"; edOut.append(mes); try { sleep((int)(Math.random()*10001)); } catch(InterruptedException e) { throw new RuntimeException(e); } SwingUtilities.invokeLater(new UpdateMessage(mes, edOut)); }}

// enz … tot class Taskn