- Thread Lifecycle | Overview
- Thread Lifecycle | Grundprinzip
- Thread Lifecycle | Thread erzeugen
- Thread Lifecycle | Lambda-Expression für run()
- Thread Lifecycle | Thread.start()
- Thread Lifecycle | Thread.stop()?
- Thread Lifecycle | Threads pausieren/fortsetzen
- Thread Lifecycle | Thread Fork
- Thread Lifecycle | Thread Join
- Thread Lifecycle | StartRunJoinDemo
- Thread Lifecycle | example-ThreadEndsSelf
- Thread Lifecycle | example-ThreadWithWhileCriteria
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 Lifecycle | Overview
Jeder Threads hat einen Lebenszyklus. Er wird geschaffen, lebt, wird von Zeit zu Zeit mal ausgeführt oder schläft. Und irgendwann hat er ein selbst gewähltes Ende oder wird im Falle einer Dauerschleife mit anderen Maßnahmen beendet.
Das Problem in der Praxis: Man hat nicht nur einen Thread sondern 2 und mehr. Es beginnt schon damit, dass der MainThread der erste Thread ist, ohne dass wir diesen erzeugen müssen. Will man mehrere Threads erzeugen und an einer bestimmten Stelle im Programm nebenläufige Prozesse wieder zusammenführen, muss man nicht mit dem Fork und Join von Threads befassen. In diesem Themenblock wählen wir den grundlegenden Weg.
Overview
Thread Lifecycle | Grundprinzip
Die Methoden start(), run(), join(), stop() dienen der Einflussnahme auf den Lebenszyklus einen Threads. Die Methodennamen wirken selbst erklärend, die wirkliche Nutzung ist es aber nicht. Es beginnt damit, dass man die Methoden run() und stop() niemals aufruft.
Thread Lifecycle | Thread erzeugen
Zum Erzeugen eines Threads benötigt man eine Instanz der
Klasse java.util.Thread. Diese kann
man mitunter über Thread t = new Thread(..);
erzeugen. Der Konstruktor ist mehrfach überladen.
Die Verwendung einer eigenen CustomThread extends Thread Klasse wurde bereits erläutert. Auch die Angabe eines Objekts, dessen Klasse Runnable implementiert hat, wurde bereits erläutert.
Als eine weitere Variante gibt es die Option, einen Thread bei seiner Erzeugung die Funktion direkt als Lambda Expression zu liefern.
Thread Lifecycle | Lambda-Expression für run()
Im Programmcode werden alle Aufgaben und damit quasi die run()-Methoden über Lambda-Expressions realisiert. Lambda-Expressions werden im Bereich der Funktionalen Programmierung erläutert.
Da ein Runnable nur eine einzige Methode fordert, und zwar die
run() Methode, und die
Thread-Klasse einen Konstruktor hierfür bietet, ist das
möglich.
Thread Lifecycle | Thread.start()
Wir können einen Thread starten, indem wir an seiner Instanz die
.start() Methode rufen.
Diese bewirkt, dass die Runtime, wenn denn der Thread wirklich ausgeführt wird und Prozessorzeit bekommt, an diesem Thread die run() Method aufruft. Die run() Methode wird also NIEMALS direkt aufgerufen.
Thread Lifecycle | Thread.stop()?
Wie die run() Methode so wird auch die
.stop() Methode niemals durch Code aufgerufen.
Ein Thread ist immer dann fertig wenn er seine run() Methode durchlaufen hat.
Will man sicherstellen, dass ein Thread vorzeitig endet, muss man über Programmlogik sicherstellen, dass die run() Methode, wenn denn diese in einer Schleife läuft, eine Abbruchbedingung bekommt.
Es gibt weitere Optionen, einen Thread abzubrechen.
Ein einmal beendeter Thread kann NICHT wiederbelebt werden und NICHT neu gestartet werden. Man muss zwinged das Thread-Objekt als neues Objekt erzeugen.
Thread Lifecycle | Threads anhalten/fortsetzen
Wenn wir einen Thread pausieren (halt/pause) und fortsetzen (resume) möchten, so realisiert man
das zumeist über Programmlogik innerhalb der run() Methode.
Es gibt weitere Varianten, aber darauf gehen wir hier an dieser Stelle nicht ein.
Thread Lifecycle | Thread Fork
Als Fork (dt. Gabel) bezeichnet man das Prinzip, dass Threads wieder intern eigene Threads starten können:
Ein jeder Thread kann in seiner run()-Methode jederzeit wiederum einen eigenen Thread starten, so dass auf diesem Wege eine Baumstruktur von Abhängigkeiten besteht.
Jeder dieser Threads läuft hierbei allerdings unabhängig, dh. ohne eine weitere Steuerung kann es sein, dass der innerste Thread länger läuft als der ihn umgebende Thread.
Thread Lifecycle | Thread Join
Dort, wo Thread.join(..) mit der Referenz auf eine Thread-Instanz wartet, blockt die weitere Code-Ausführung. Dort, wo ein Thread.join(..) allerdings fehlt, kann es passieren, dass der den inneren Thread umschließende lange Thread eher beendet wird als der innere Thread.
Threads mit Runnables haben keinen Rückgabewert
Darauf wird noch im Detail eingegangen, aber früher hatten die von Threads verwaltete Runnables keinen Rückgabewert. Man muss also immer eine Lösung finden, wie man, wenn eine Thread dort fleißig gearbeitet hat, eigentlich das Ergebnis bekommen kann.
Mit thread.join(..) konnte wenigstens auf das Ende eine Threads gewartet werden.
Demo
Thread Lifecycle | StartRunJoinDemo
Das Programm startet drei Threads: Einen langen Thread und einen+ kurzen Thread. Der lange Thread erzeugt wiederum innerhalb eines funktionalen Ausdrucks einen inneren Thread. Das Hauptprogramm wartet über einen Thread-Join darauf, dass der lange und kurze Thread beendet wird und blockt in dieser Zeit.
package com.stuelken.java.b4.parallel.c02threadslifecycle;
/**
*
* @author t2m
*
*/
public class StartRunJoinDemo {
public static void main(String[] args) throws InterruptedException {
/*
* {#1} Erzeugen eines Threads
*/
Runnable lang = () -> {
System.out.println("lang() begonnen. ");
Runnable inner = () -> {
System.out.println("inner() begonnen. ");
try {
Thread.sleep(10000);
} catch (InterruptedException ignored) {
}
System.out.println("inner() beendet. ");
};
Thread innerTask = new Thread(inner);
System.out.println("innerTask.start! ");
innerTask.start();
try {
Thread.sleep(5000);
} catch (InterruptedException ignored) {
}
System.out.println("lang() beendet.");
};
Thread langTask = new Thread(lang);
Runnable kurz = () -> {
System.out.println("kurz() begonnen. ");
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) {
}
System.out.println("kurz() beendet");
};
Thread kurzertask = new Thread(kurz);
Thread langertask = new Thread(lang);
System.out.println("langertask.start ");
langertask.start();
System.out.println("kurzertask.start ");
kurzertask.start();
System.out.println("Warte auf langertask");
System.out.println("Warte auf kurzertask");
langertask.join();
kurzertask.join();
System.out.println("Alle Aufgaben abgeschlossen");
}
}
// @formatter:off
/*
langertask.start
kurzertask.start
Warte auf langertask
Warte auf kurzertask
lang() begonnen.
kurz() begonnen.
innerTask.start!
inner() begonnen.
kurz() beendet
lang() beendet.
Alle Aufgaben abgeschlossen
inner() beendet.
*/
Zusammenfassung
Threads können intern weitere Threads starten.
Will man sicherstellen, dass die einen Thread startende Funktion erst beendet wird, wenn der innere Thread beendet wurde, muss über Thread.join(..) mit Referenz auf den Thread blockend gewartet werden.
Overview
Thread Lifecycle | example-ThreadEndsSelf
Hinweis: Beispiel fehlt noch.
Overview
Thread Lifecycle | example-ThreadWithWhileCriteria
Ein früher übliches Verfahren bestand darin, Threads
über ein Kriterium in der while(..) Schleife beenden zu können.
Beispiel: Hauptklasse.sollFortsetzen() könnte als statische
Methode an irgendeinem Punkt false
liefern.
Es gibt längst darüber hinaus Varianten mit denen das einfacher und besser geht.
Hinweis: Beispiel fehlt noch.
UIO3 Es ist einfacher als Du denkst.
Stelle noch heute Deine Anfrage.
