package javacodebook.thread.wait_notify; import java.util.Vector; /** * Eine Message-Queue. Jede Nachricht wird in einem Vector gespeichert. Der * Empfang einer Nachricht und das Senden einer Nachricht können nicht gleich- * zeitig erfolgen, da die einzelnen Blöcke synchronisiert sind. Ist die * Queue voll bzw. leer, müssen sendende bzw. lesende Threads warten. */ public class MessageQueue { Vector queue; int maxSize; public MessageQueue(int size) { this.maxSize = size; queue = new Vector(size); } /** * Fügt eine neue Nachricht an das Ender der Message-Queue an. Nur ein * Thread kann gleichzeitig eine Nachricht anfügen. In dieser Zeit kann * auch kein Thread eine Nachricht aus der Queue lesen. Die Queue hat * eine max. Grösse. Bei erreichen dieser Grössen müssen Threads, die * Nachrichten in die Queue schreiben möchen, warten, bis mind. eine * Nachricht aus der Queue gelesen und damit entfernt wurde. */ public synchronized void send(Object obj) { // Solange warten, bis die Queue nicht mehr voll ist. while (queue.size() == maxSize) { System.out.println( Thread.currentThread().getName() + ": Queue ist voll. Thread muss warten" ); try { wait(); } catch (Exception e) {} } System.out.println( Thread.currentThread().getName() + ": schreibt Nachricht in die Queue." ); // Nachricht in die Queue schreiben queue.addElement(obj); notify(); } /** * Liest die älteste Nachricht aus der Message-Queue aus. Nur ein Thread * kann gleichzeitig eine Nachricht lesen. In dieser Zeit kann auch kein * Thread eine neue Nachricht an die Queue anhängen. Ist die Queue leer * müssen Threads solange warten, bis mind. eine Nachricht in die Queue * geschrieben wurde. */ public synchronized Object recv() { // Solange warten, bis mind. eine Nachricht in der Queue bereitsteht while (queue.size() == 0) { System.out.println( Thread.currentThread().getName() + ": Queue ist leer. Thread muss warten" ); try { wait(); } catch (Exception e) {} } System.out.println( Thread.currentThread().getName() + ": liest Nachricht aus der Queue." ); // Nachricht aus der Queue lesen. Object obj = queue.firstElement(); queue.removeElementAt(0); notify(); return obj; } } --- Neue Klasse --- package javacodebook.thread.wait_notify; import java.util.Random; /** * Ein Thread, der versucht, Nachrichten aus einer MessageQueue zu lesen. */ class ReceiverThread extends Thread { private static Random random = new Random(System.currentTimeMillis()); private MessageQueue queue; private int sleepMax; /* * Der Thread wird mit einem Namen und der MessageQueue initialisiert */ public ReceiverThread(String name, MessageQueue queue, int sleepMax) { super(name); this.queue = queue; this.sleepMax = sleepMax; } /** * Solange es etwas zu lesen gibt, liest der Thread Nachrichten aus der * Queue und schläft zwischendurch für eine zufällige Zeit lang. */ public void run() { Object msg = null; while(true) { sleepRandomly(); msg = queue.recv(); if (msg == null) break; System.out.println(getName() + ": Nachricht erhalten: " + msg); } } private void sleepRandomly() { try { sleep(random.nextInt(sleepMax)); } catch (Exception ignore) {} } } --- Neue Klasse --- package javacodebook.thread.wait_notify; import java.util.Random; /** * Ein sendender Thread. Er schreibt in eine MessageQueue Nachrichten, die von * einem anderen Thread wieder aus der Queue ausgelesen werden können. */ class SenderThread extends Thread { private static Random random = new Random(System.currentTimeMillis()); private MessageQueue queue; private int sleepMax; /* * Der Thread wird mit einem Namen und der MessageQueue initialisiert */ public SenderThread(String name, MessageQueue queue, int sleepMax) { super(name); this.queue = queue; this.sleepMax = sleepMax; } /** * Der Thread schreibt Nachrichten in die MessageQueue und schläft * zwischendurch für eine zufällige Zeit lang. */ public void run() { int index = 0; while(true) { queue.send(getName() + " " + index); index++; sleepRandomly(); } } private void sleepRandomly() { try { sleep(random.nextInt(sleepMax)); } catch (Exception ignore) {} } } --- Neue Klasse --- package javacodebook.thread.wait_notify; public class Starter { public static void main(String []args) { MessageQueue queue = new MessageQueue(3); Thread send1 = new SenderThread("Anton", queue, 200); Thread send2 = new SenderThread("Berta", queue, 200); Thread recv1 = new ReceiverThread("Charly", queue, 200); Thread recv2 = new ReceiverThread("Dora", queue, 200); send1.start(); send2.start(); recv1.start(); recv2.start(); } }