- Thread Notification | Overview
- Thread Notification | Grundlagen
- Thread Notification | wait
- Thread Notification | notify
- Thread Notification | notifyAll
- Thread Notification | sleep
- Thread Notification | sleep oder wait?
- Thread Notification | ThreadNotificationDemo
- Thread Notification | Zusammenfassung
JAVA-B4
Parallel Computing (Parallelism)
Parallelism
Multithreading
Klassische Threads
Threads & Runnables
Overview
Thread (Begriff)
DruckThread
DruckRunnable
ThreadDemo
Output
Thread Lifecycle
Overview
start()
run()
join()
stop()?
StartRunJoinDemo Example
Von allein endende Threads
Threads mit while(criteria)
Daemon-Threads
Overview
ThreadDaemonDemo
Daemon (Summary)
Thread-Priority
Overview
t.setPriority(..)
MachineThread Klasse (Example)
ThreadPriorityDemo (Example)
Thread Notification
Grundlagen
wait
notify
notifyAll
sleep
sleep vs. wait
Thread Notification Demo
sychronized(monitor)
Notification/Monitor Zusammenfassung
Concurrent API
Vom Thread zur Concurrent API
Was ist Concurrency?
Was ist Concurrency?
Problemstellungen bei herkömmlichen Threads
Features der Concurrent API
Warum: Bedeutung des Umstiegs
Themenüberblick
Technischer Hintergrund
Thread.sleep(0, 500_000)
System.nanoTime()
Executors (Übersicht) #310
ExecutorService (Page)
Begriffsbestimmung
Excetutor
.execute()
ExecutorService (Begriff)
ExecutorService Interface Methoden
Mehrere Callables und Runnables auf einmal starten
Kontrolliertes Beenden
Executors-Utilily Klasse
newCachedThreadPool()
newSingleThreadExecutor()
newFixedThreadPool(int nThreads)
newWorkStealingPool()
newScheduledThreadPool(int corePoolSize)
Beispiel
ForkJoinPool, RecursiveTask, Executors Example#09
A | B1,B2,B3 | C mit Summenbildung.
Executor vs. ExecutorService Example#10
Executors.newFixedThreadPool(2)
Beispiel
Zusammenfassung Executors
Callable, Future #330
Callable Future (Begriff)
Callable Interface (Begriff)
Begriff
Callable erzeugen
Callable verwenden
Future
Beispiel
Future-Listen mit invokeAll
Was sind Future-Listen?
Wie erzeuge ich Future-Listen?
Wann blockt eine Future-Liste?
Beispiel mit 12 Callables in 4 Gruppen
Executors (#350) @! Bis auf Hinweis doppelt
Overview
Executor (Begriff)
ExecutorService (Begriff)
Executors.new~ Factory Methoden
Executors für ThreadPoolExecutor mit fixed Pool
ScheduledExecutorService
ScheduledExecutorService
Superklasse ExecutorService
schedule(*)
scheduleAtFixedRate(*)
scheduleWithFixedDelay(*)
ScheduledExecutorService (xmpl)
ProductClock(Main, Bsp.)
AbstractMachine**
AbstractMaterial**
Coal/Iron/Steel**
Coal-/Iron-/Steel-Machine**
Material**
ProductionBus-Machine**
Storage T**
ThreadPoolExecutor (Detail)
Executor Implementierung
ThreadPoolExecutor (Term)
ThreadPoolExecutor Beispiele
"FixedSizeExecutorExample" EXAMPLE C20
"CachedExecutorExample" EXAMPLE C21
SynchronousQueue
"ScheduledExecutorExample" EXAMPLE C22
"CustomSingleThreadExecutorRunnableComponent" EXAMPLE C23
"CustomPolicyRejectedExecutorExample" EXAMPLE C24
"PrioritizedCombinerRunnableComponent" EXAMPLE C30
"BufferingRejectedTasksExample" EXAMPLE C31
Java RejectedExecutionHandler
ThreadPoolExecutor FAQ
Synchronizer
Synchronizer (overview)
Synchronizer Begriff
CountDownLatch
CountDownLatch Example
CyclicBarrier
CyclicBarrier Example (@Zeit ausgeben!)
Phaser
Phaser Example(@Erl!)
Exchanger
Exchanger ping/pong
Semaphore
CompletableFuture
async!!!
SemaphoreCompletableFutureDemo (@!?)
Monitoring
JMX
ThreadPoolExecutor "live" überwachen
getActiveCount()
getPoolSize()
getCompletedTaskCount()
getQueue().size()
Concurrency
Example:DeterministicCopy @todo FILE LINK FEHLT!
Example:NonDeterministicCopy @todo FILE LINK FEHLT!
Kapitel java.util.concurrent.Flow @!fehltReactive Flow @!fehltPublisher TSubscriber TSubscription TProcressor TProcressor T
Overview
Thread Notification | Overview
Threads werden früher oder später Daten austauschen und hierbei den Zugriff auf Daten steuern müssen. Zu diesem Zweck ist es möglich, sich einen Monitor zu erzeugen und den Zugriff hierauf zu synchronisieren. Die Voraussetzung für eine Zusammenarbeit der Threads besteht darin, dass sich diese gegenseitig rund um den Lock des Monitors benachrichtigen können.
Wir erzeugen uns einen Monitor und spielen die Notification durch.
Grundlagen
Thread Notification | Grundlagen
In Zeiten, in denen man Threads ohne die neue java.util.concurrent-Klasse oder auch neuere Packages programmierte, sah es auf den ersten Blick ganz einfach aus: Thread erzeugen. Wenn der Thread auf einen anderen warten sollte, erstellte man sich ein Objekt als Monitor.
Methode .wait()
Mit .wait() wird der Monitor
freigegeben und auf ein Signal gewartet.
.wait() funktioniert nur innerhalb eines
synchronized(monitorObjekt)
Blocks.
notify()
.notify() weckt
einen bestimmten wartenden Thread.
.notify() funktioniert nur innerhalb eines
synchronized(monitorObjekt)
Blocks.
notifyAll()
.notifyAll() weckt
alle wartenden Threads.
.notifyAll() funktioniert nur innerhalb eines
synchronized(monitorObjekt)
Blocks.
sleep()
.sleep() bewirkt, dass
dieser Thread in dem Thread, in welchem er läuft,
eine Weile schlafen und dahingehend von einer Ausführung
ausgenommen werden soll.
Während .wait() explizit
auf ein Signal wartet, warten .sleep(..)
eine in Millisekunden angegebene Zeitspanne.
sleep() oder wait()?
sleep(..) ist gerade im Falle
von run()-Methoden, welche in Dauerschleifen wie while(true)
oder while(abbruchBedingung) laufen, dringend anzuraten,
damit nicht eine Schleife als Dauerschleife den Prozessor
so stark auslastet, dass die anderen Threads nicht zum
Zuge kommen.
Selbst ein Threads.sleep(2)
von nur 2/1000stel Sekunden kann für Ordnung sorgen.
Wenn man allerdings auf eine Ressource bzw. auf einen
Monitor wartet und nicht bekannt ist, ob man nun
1 Nano-Sekunde oder 30 Sekunden warten muss, besteht bei
.wait() der Reiz darin,
dass ein Thread einfach auf ein Signal wartet und damit
nicht ständig alle 1/1000 Sekunde schlafen zu gehen.
Auf .wait kann
viel schneller reagiert werden.
Ausblick
Hinweis: Diese Mechanismen wurden später in späteren Java-Versionen
durch Lock & Condition
(java.util.concurrent.locks) verfeinert.
Die Methoden wait()/notify() sind im klassischen Thread-Modell allerdings grundlegend.
ThreadNotificationDemo
Thread Notification | ThreadNotificationDemo
Ein Daten-Consumer benötigt Daten von einem Daten-Producer. Beides sind Threads und laufen voneinander unabhängig, aber der Consumer wartet bereits auf die Daten, bevor der Producer überhaupt gestartet wird.
Anstelle der Synchronisation der Variabler
data wird ein
anderes einfaches Objekt als Monitor
synchronisiert.
Wer gerade den LOCK auf den Monitor hat, darf seinen Teil ausführen und benachrichtigt anschließend die anderen, dass der Monitor wieder frei ist.
Code
package com.stuelken.java.b4.parallel.c05threadnotification;
/**
* @author t2m
*/
public class ThreadNotification {
/**
* Dieses Objekt dient als Monitor.
*/
static final Object monitor = new Object();
/**
*
*/
static String data = null;
/**
* @param args Keine Argumente
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// {#1} Ein Thread welcher vor einer Ausführung den Zugriff auf monitor fordert.
Thread producer = new Thread(() -> {
// Dieser Code-Block blockt so lange, bis der Thread den Zugriff
// auf die monitor-Variable bekommt. Nach Abschluss werden
// alle anderen wartenden Threads benachrichtigt, dass die
// Variable wieder frei ist.
synchronized (monitor) {
System.out.println("Producer: Beginne 5-Sekunden-Prodution.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
data = "DATA (ProducerThread hat Daten erzeugt)";
System.out.println("Producer: Daten bereit: notifyAll()");
monitor.notifyAll(); // Weckt alle
}
});
producer.setName("Producer Thread");
// {#2} Ein zweiter Thread als Consumer.
Thread consumer = new Thread(() -> {
// Auch dieser Codeblock wird erst ausgeführt, wenn
// der Thread den Zugriff auf die Ressource monitor
// erlangt hat.
synchronized (monitor) {
// {#3} Wenn wir den Zugriff auf den Monitor haben, der Wert von data aber noch
// null ist, dann teilen wir dem Monitor-Objekt mit, dass wir warten wollen.
while (data == null) {
try {
System.out.println("Consumer: wartet auf Daten: monitor.wait()");
monitor.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println("Consumer: Daten empfangen: " + data);
}
});
// {#4} Consumer starten und warten lassen.
System.out.println("main: Consumer.start()");
consumer.start();
try {
Thread.sleep(5000);
} catch (InterruptedException ignored) {
}
// {#5} Producer starten lassen.
System.out.println("main: Producer.start()");
producer.start();
System.out.println("main: Producer.gestartet()");
// {#6} Hauptprogramm warten lassen.
producer.join();
consumer.join();
System.out.println("main: Alle Threads beendet.");
}
}
Ausgabe
// @formatter:off
/*
main: Consumer.start()
Consumer: wartet auf Daten: monitor.wait()
main: Producer.start()
main: Producer.gestartet()
Producer: Beginne 5-Sekunden-Prodution.
Producer: Daten bereit: notifyAll()
Consumer: Daten empfangen: DATA (ProducerThread hat Daten erzeugt)
main: Alle Threads beendet.
*/
Thread Notification | Zusammenfassung
Ein Monitor kann vom Prinzip her ein ganz einfaches beliebiges Objekt sein. Dieses Objekt dient einzig und allein dazu, dass nur der Thread seine Aktionen gerade ausführen kann, welcher einen Lock auf diesen Monitor hat.
Dieses Verfahren hat den Vorteil, dass Threads auf ein Signal warten können und nicht wie im Falle von sleep(..) alle paar Zeiteinheiten es erneut versuchen müssen.
siehe auch: ThreadLock.
UIO3 Es ist einfacher als Du denkst.
Stelle noch heute Deine Anfrage.
