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 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.

UI ORGANIZED.

UIO3 Es ist einfacher als Du denkst.

Stelle noch heute Deine Anfrage.

uio--WebPageFooter-Module