package javacodebook.thread.syncblock2; 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. */ public class MessageQueue { Vector queue = new Vector(); /** * Fügt eine neue Nachricht an das Ende 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. */ public synchronized void send(Object obj) { queue.addElement(obj); } /** * 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. */ public synchronized Object recv() { if (queue.size() == 0) return null; Object obj = queue.firstElement(); queue.removeElementAt(0); return obj; } } --- Neue Klasse --- package javacodebook.thread.syncblock2; import java.util.Random; /** * Ein lesender Thread. Er liest aus einer MessageQueue Nachrichten, die von * einem anderen Thread in die Queue geschrieben wurden. */ class ReceiverThread extends Thread { private static Random random = new Random(System.currentTimeMillis()); private MessageQueue queue; private boolean stop = false; public ReceiverThread(String name, MessageQueue queue) { super(name); this.queue = queue; } public void run() { // Der Empfänger liest solange Daten aus der MessageQueue, bis die // Queue leer ist und der Thread gestoppt werden soll. Zwischen zwei // Versuchen, eine Nachricht zu lesen, schläft der Thread zwischen 0 // und 1 Sekunde. Object msg = null; while(stop == false || msg != null) { sleepRandomly(1000); msg = queue.recv(); if (msg == null) System.out.println("Queue ist leer"); else System.out.println(msg); } } private void sleepRandomly(int max) { try { sleep(random.nextInt(max)); } catch (Exception ignore) {} } /** * Der Thread soll gestoppt werden */ public void stopExecution() { this.stop = true; } } --- Neue Klasse --- package javacodebook.thread.syncblock2; 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; public SenderThread(String name, MessageQueue queue) { super(name); this.queue = queue; } public void run() { // Der Sender schreibt 8 mal Daten in die MessageQueue und beendet sich // anschliessend. Zwischen den Schreibvorgängen schläft der Thread // zwischen 0 und 1 Sekunde. for (int i=0; i<8; i++) { queue.send(getName() + ": " + i); sleepRandomly(1000); } } private void sleepRandomly(int max) { try { sleep(random.nextInt(max)); } catch (Exception ignore) {} } } --- Neue Klasse --- package javacodebook.thread.syncblock2; /** * Startet zwei Thread. Der erste Thread schreibt Nachrichten in eine Queue, * der zweite liest die Nachrichten aus der Queue wieder aus. */ public class Starter { public static void main(String []args) throws Exception { MessageQueue queue = new MessageQueue(); SenderThread send = new SenderThread("Anton", queue); ReceiverThread recv = new ReceiverThread("Berta", queue); send.start(); recv.start(); // Der Haupthread wartet so lange, bis der sendende Thread seine Arbeit // erledigt hat und stoppt anschliessend den lesenenden Thread. send.join(); recv.stopExecution(); } }