1. Example 01: HipHop
1.1. Aufgabenstellung
Erstellen Sie ein Programm mit zwei Threads, das die beiden Wörter "Hip" und "HOP" in einer Endlosschleife unterschiedlich schnell ausgibt.
Realisieren Sie zwei Programmvarianten:
-
Ableitung von der Klasse
Thread
-
Implementierung des Interfaces
Runnable
.
1.2. Bildschirmausgabe
Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip Hip Hip Hip Hip HOP Hip
Lösung: HipHop2
3. Example 03: start/stop eines Threads
3.1. Aufgabenstellung
Entwickeln Sie eine Klasse, die das Interface Runnable implementiert sowie die Methoden
-
main,
-
start und
-
stop.
start erzeugt einen neuen Thread und startet ihn, stop beendet ihn.
Für jeden neu erzeugten Thread ist auch ein neuer Name zur Unterscheidung zu wählen. Der Thread soll seinen Namen in Abständen von zwei Sekunden ausgeben.
In main können die Methoden start und stop, gesteuert über Tastatureingabe, aufgerufen werden.
Verwenden Sie zur Tastatureingabe System.in.read()
|
4. Example 04: Logger
4.1. Aufgabenstellung
Zwei parallel laufende Threads sollen Nachrichten in dieselbe Protokolldatei schreiben.
Entwickeln Sie die Klasse LogFile, die die Protokolldatei verwaltet. Die Klasse soll die Methode
public synchronized void writeLine(String msg)
enthalten, die eine Zeile bestehend aus Systemzeit und msg schreibt.
Erstellen Sie ein Testprogramm, das die Protokolldatei erzeugt, zwei Threads startet, die in diese Datei mehrere Nachrichten schreiben, und das die Datei schließt, nachdem die Ausführung der beiden Threads beendet ist.
Verwenden sie die Klasse DateTimeFormatter |
4.2. Bildschirmausgabe
Thread Thread-0 gestartet Thread Thread-1 gestartet Warte auf Beendigung beider Threads ... Ende Process finished with exit code 0
4.3. Datei
01.04.2020 21:59:18 Thread-0 01.04.2020 21:59:18 Thread-0 01.04.2020 21:59:18 Thread-0 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-0 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 01.04.2020 21:59:18 Thread-1 ...
5. Example 05: Bankkonto
5.1. Aufgabenstellung
Schreiben Sie ein Programm, in dem mehrere Threads zur gleichen Zeit einen zufälligen Betrag auf dasselbe Konto einzahlen.
Die Additionsmethode soll aus den einzelnen Threads mehrfach aufgerufen werden.
Vergleichen Sie am Ende die überwiesenen Beträge der einzelnen Threads mit dem Gesamtsaldo am Konto. Stimmen beide Beträge nicht überein, haben Sie eine Race Condition.
Schreiben Sie das Programm so, dass keine Additionen verloren gehen.
5.2. Hinweise zur Implementierung
5.2.1. Überblick
Das Programm besteht aus drei Klassen:
-
Konto: Die ist die geteilte Ressource
-
Manager: Der jeweilige Task. Zählt die Anzahl der Transaktionen sowie die Betragssumme.
-
Test: Startet die Threads mit ihren Tasks (Manager), wartet 10 sek., unterbricht alle Threads und sammelt schließlich die Ergebnisse ein (Anzahl Transaktionen und gebuchter Betrag).
5.2.2. Klasse Konto
Pseudo-Code für Methode add(…):
-
Der saldo wird in eine lokale Variable eingelesen.
-
Die Verarbeitung dauert 10 ms (→
Thread.sleep(10)
) -
Der Betrag
value
wird zumsaldo
addiert.
5.2.3. Klasse Manager
Pseudo-Code für Methode run(…):
-
Ermittle per Zufall einen Wert (value) zwischen 1 und 10;
-
konto.add(value)
-
Inkrementiere 'transaktionen'
-
Summiere den
value
zu summe -
Warte 2 Millisekunden
5.2.4. Klasse Test
Pseudo-Code für Methode main(…):
-
Erstelle ein Konto für sämtliche Threads
-
Erstelle eine Map und speichere als key den Thread und als Value den Manager
-
Erstelle Threads und Manager in der gewünschten Anzahl (ANZAHL_THREADS) und starte diese.
-
Warte die gewünschte Zeit (SEKUNDEN)
-
Unterbreche alle Threads (interrupt)
-
Warte bis alle Threads fertig sind und
-
sammle die Ergebnisse ein (Transktionen und Summe)
-
Gib den Kontostand sowie die Gesamttransaktionen und Gesamtsummen der Threads auf der Console aus.
Wird ein Thread während des sleep unterbrochen, ist in der catch-Klausel wieder ein interrupt aufzurufen try { Thread.sleep(10); } catch (InterruptedException e) { ... Thread.currentThread().interrupt(); } |
5.3. Bildschirmausgabe
main: Warte 10 Sekunden ... Gesamtanzahl Transaktionen: 969 Gesamtsumme: 5269 Saldo: 5269 Process finished with exit code 0
5.4. Erweiterung
Ergänzen Sie die Klassen Konto
und Manager
mit einem Java-Logger.
Jedesmal, wenn ein Thread im sleep unterbrochen wird (interrupt), ist eine Meldung auszugeben:
Apr 10, 2020 10:31:42 AM at.htl.multithreading.exercise.ex05.Konto add SEVERE: Thread-6: Konto.add() interrupted
Verwenden Sie hierzu den java.util.Logger:
private static final Logger LOG = Logger.getLogger(Konto.class.getSimpleName());
Dieser Logger soll ausschließlich in eine Datei "KontoLogger.txt" schreiben:
Handler fileHandler = new FileHandler("KontoLogger.txt");
LOG.addHandler(fileHandler);
Schalten Sie hierzu den ConsoleHandler aus:
LOG.setUseParentHandlers(false);
Das vorgegebene Ausgabeformat erhalten sie durch Verwendung eines SimpleLoggers:
fileHandler.setFormatter(new SimpleFormatter());
Apr 10, 2020 10:31:42 AM at.htl.multithreading.exercise.ex05.Konto add SEVERE: Thread-6: Konto.add() interrupted