uio--WebPageMain-Module

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.

UI ORGANIZED.

UIO3 Es ist einfacher als Du denkst.

Stelle noch heute Deine Anfrage.

uio--WebPageFooter-Module