Hogeschool Gent Datacommunicatie en netwerken Johan Van Schoor Bert Van Vreckem 2006-2007 Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 1 Project Groepswerk (per 2) Netwerkapplicatie schrijven in Java Opgaven: zie dokeos ofwel eigen voorstel Evt. combineren met ander vak Deadline: laatste oef les Op tijd! (zoniet sanctie) CD+dossier met afgewerkt product Programma draait zelfstandig, buiten een IDE Gebruikershandleiding Dossier over achterliggende technologie, ontwerp, ... Demo op zie dokeos Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 2 Project – opgaven Peer-to-peer filesharing over een LAN Chatprogramma Mailserver Webserver Webcache RFC implementatie Eigen voorstel? Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 3 Het belang van threads Onontbeerlijk in netwerkprogramma's (met sockets) Client: Snel reageren op invoer gebruiker Communicatie met de server Server: Verbindingen met verschillende clients tegelijk Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 4 Een thread stoppen Door de method run() op een normale manier te laten eindigen: De thread houdt de waarde van een variabele in het oog die aangeeft of de thread moet stoppen Eventueel een extra variabele als je de thread tijdelijk wil stilleggen (“suspend”) NIET met stop(), suspend() of resume(): deprecated Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 5 Threads in Java 1.5. De overgang naar 1.5. brengt belangrijke wijzigingen mee i.v.m. multithreading. Gebruiken de Runnable interface ipv een subklasse van Thread. Gebruiken een ThreadPool die threads bevat die de Runnable objecten uitvoeren. Geen start() meer nodig. Synchronisatie gebeurt via lock en unlock op een extra object van de klasse ReentrantLock. De klasse ReentrantLock levert Condition objecten waarmee de synchronisatie tussen de verschillende threads die een object delen kan worden geregeld. await de thread komt in wait state signal de thread komt terug in de runnable state Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 6 Voorbeeld: Twee threads (1). import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadHelloCount { public static void main(String[] args) { HelloThread hello = new HelloThread(); CountThread count = new CountThread(); ExecutorService threadExecutor = Executors.newFixedThreadPool(2); threadExecutor.execute( hello ); threadExecutor.execute( count ); threadExecutor.shutdown(); System.out.printf("MainThread finished\n"); } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 7 Voorbeeld: Twee threads (2). class HelloThread implements Runnable { private static Random generator =new Random(); } public void run() { for (int i=0; i<5; i++) { try { System.out.printf("Hello!\n"); Thread.sleep(generator.nextInt(3000)); } catch (InterruptedException e) { System.out.println(e.toString()); } } System.out.printf("HelloThread finished\n"); } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 8 Voorbeeld: Twee threads (3). class CountThread implements Runnable { private static Random generator = new Random(); } public void run() { for (int i=0; i<5; i++) { try { System.out.printf("%d\n",i+1); Thread.sleep(generator.nextInt(3000)); } catch (InterruptedException e) { System.out.println(e.toString()); } } System.out.printf("CountThread finished\n"); } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 9 Voorbeeld: Twee threads (4). Mogelijke uitvoer: Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 10 Voorbeeld: Thread Synchronisatie (1). public interface Buffer { public void set( int value ); public int get(); } import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; public class SynchronizedBuffer implements Buffer { private Lock accessLock = new ReentrantLock(); private Condition canWrite = accessLock.newCondition(); private Condition canRead = accessLock.newCondition(); private int buffer; private boolean occupied = false; Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 11 Voorbeeld: Thread Synchronisatie (2). public void set( int value ) { accessLock.lock(); try { while ( occupied ) { canWrite.await(); } buffer = value; occupied = true; canRead.signal(); } catch ( InterruptedException e ) { e.printStackTrace(); } finally { accessLock.unlock(); } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 12 Voorbeeld: Thread Synchronisatie (3). } public int get() { int readValue = 0; accessLock.lock(); try { while ( !occupied ) { canRead.await(); } occupied = false; readValue = buffer; canWrite.signal(); } catch ( InterruptedException e ) { e.printStackTrace(); } finally { accessLock.unlock(); } return readValue; } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 13 Voorbeeld: Thread Synchronisatie (4). import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class SynchronizedThreadApp { public static void main(String []arg) { ExecutorService threadExecutor = Executors.newFixedThreadPool(2); Buffer shared = new SynchronizedBuffer(); } } threadExecutor.execute( new Producer(shared); threadExecutor.execute( new Consumer(shared) ); threadExecutor.shutdown(); Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 14 Voorbeeld: Thread Synchronisatie (5). class Producer implements Runnable { private Buffer shared; private static Random generator = new Random(); } public Producer(Buffer sb) { shared=sb; } public void run() { for(int i = 1; i <=10; i++) { try { Thread.sleep(generator.nextInt(2000)); } catch (InterruptedException e) { System.out.println(e.toString()); } shared.set(i); } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 15 Voorbeeld: Thread Synchronisatie (6). class Consumer implements Runnable { private Buffer shared; private static Random generator = new Random(); public Consumer(Buffer sb) { shared=sb; } public void run() { for(int i = 0; i <10; i++) { try { Thread.sleep(generator.nextInt(2000)); } catch (InterruptedException e) { System.out.println(e.toString()); } System.out.printf("%4d",shared.get()); } System.out.println(); } } Uitvoer: rij getallen van 1 tot 10. Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 16 Voorbeeld: Thread Synchronisatie met BlockingQueue (1). import java.util.concurrent.ArrayBlockingQueue; public class BlockingBuffer implements Buffer { private ArrayBlockingQueue<Integer> buffer; public BlockingBuffer() { buffer = new ArrayBlockingQueue<Integer>( 3 ); } public void set( int value ) { try { buffer.put( value ); // indien er geen plaats is // in de queue wordt er gewacht (wait state) } catch ( InterruptedException e ) { e.printStackTrace(); } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 17 Voorbeeld: Thread Synchronisatie met BlockingQueue (2). public int get() { int readValue = 0; try { readValue =buffer.take();//indien er geen waarden // in de queue zijn wordt er gewacht (wait state) } catch ( InterruptedException e ) { e.printStackTrace(); } return readValue; } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 18 Voorbeeld: Thread Synchronisatie met BlockingQueue (3). import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class BlockingBufferThreadApp { public static void main(String []arg) { ExecutorService threadExecutor = Executors.newFixedThreadPool(2); Buffer shared = new BlockingBuffer(); threadExecutor.execute( new Producer(shared) ); threadExecutor.execute( new Consumer(shared) ); threadExecutor.shutdown(); } } Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 19 Oefening multithreading: Clients requests. Start een “Server thread” en drie “Client Threads”. De clients sturen elk 5 berichten (in dit geval: hun naam) naar de server op met random tijdsverloop (telkens tussen 0 en 3 sec) De server vangt de verschillende berichten op en drukt ze af op console. Na 15 berichten sluit de server thread af. Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 20 Oefening multithreading: Clients requests. Mogelijke output : Datacommunicatie en netwerken – Johan Van Schoor, Bert Van Vreckem – 2006-2007 p. 21