Multithreading in Java SE 7 mit java.util.concurrent

Transcription

Multithreading in Java SE 7 mit java.util.concurrent
Java Concurrency
Multithreading in Java SE 7 mit java.util.concurrent
Im Rahmen der Vorlesung
Parallele Programmierung – G.Fröhlich WS 14/15
Von M. Hilberg
Multithreading – Probleme?
2/27
Inhalt
●
Einleitung Java Threads
●
Interface Callable/Runnable
●
Keyword Synchronized, Volatile
●
Atomic
●
Executors
●
ConcurrentCollections
●
Future
●
(CyclicBarrier)
●
(Locks)
●
Quellen
3/27
Einleitung Java Threads
●
Meiste JVMs laufen als Single Process
●
Parallele Programmierung mittels Threads
●
●
●
Jede Applikation hat mind. 1 Thread (Mainthread). Dieser kann
andere Threads als Runnable oder Callable Objects erstellen.
Threads teilen sich Ressourcen (Speicher, Dateien). Effiziente, aber
problematische Kommunikation. Deshalb: Concurrency Klassen!
Verwendung der Concurrency Klassen wg.
–
Reduzierung der Programmieraufwands (Verwendung des
Standards)
–
Erhöhung der Performance (Implementierung ist optimiert)
–
Erhöhung der Zuverlässigkeit
4/27
Interface Runnable
5/27
Interface Runnable
●
KEIN Return value
●
KEINE checked Exception kann geworfen werden
●
Thread Methoden:
–
start()
–
Join()
–
interrupt() → benötigt im Thread periodische Abfrage
“if (interrupted()) {return;}”
–
Thread.sleep(1000)
–
CurrentThread() → Refferenz auf aktuellen Thread
–
isAlive()
6/27
Interface Callable
●
public interface Callable<V> ab Java 1.5
●
Return value!
●
Kann Exception werfen!
●
Call() Methode
7/27
Synchronized
●
●
●
Synchronized Methoden und synchronized Blocks
Die Java-Superklasse Object beinhaltet als Eigenschaft eine
Sperre. Da jede Klasse von Object abgeleitet ist, besitzen alle
Klassen diese Eigenschaft.
Das Sperren gehorcht dem “acquire-release Protokoll”:
–
Die Sperre wird gesetzt (acquire), beim Betreten einer
synchronized-Methode (oder synchronized Blocks) und entfernt
(release) bei Verlassen des Blocks (auch bei Verlassen durch
eine Exception).
8/27
Synchronized
●
Verwendung synchronized:
“Wenn von mehreren Threads auf ein Objekt zugegriffen wird, wobei
mindestens ein Thread den Zustand (repräsentiert durch die Werte der
Attribute) des Objekts ändert, dann müssen alle Methoden, die auf
den Zustand lesend oder schreibend zugreifen, mit synchronized
gekennzeichnet werden.”
9/27
Volatile
Synchronisation des Zugriffs auf Variable
●
keine threadsafty
●
„Ist eine Variable als volatile deklariert, muss die JVM
sicherstellen, dass alle zugreifenden Threads ihre
Kopien aktualisieren, sobald die Variable geändert
wird. „
●
Vorteil gegenüber synchronized: keine Code Locks
●
Nachteil: Variable muss bei Zugriff aktualisiert werden
10/27
Synchronized vs. Volatile
Am Vergleich eines Singleton:
Singleton:
●
verhindert mehrfache Erzeugung der Objekte einer Klasse
●
privater Konstruktor verhindert Erzeugung von mehreren Objekten
●
static Methode erlaubt Erzeugung eines einzigen Objektes
●
Objekt wird in privater Variable gespeichert
●
weitere Aufrufe liefern das vorher erzeugte Objekt
●
static Methode muss bei parallelem Zugriff synchronisiert werden
11/27
Synchronized vs. Volatile
Sauber, aber eventl langsam wg. großer sync. Methode
Mit volatile kleinerer sync Bereich möglich. Nicht vor J2SE 5.0
benutzen wg double-check bug!
12/27
Atomic
●
atomic sind alle read ODER write Zugriffe auf eine
Variable (außer long und double )
●
long / double muss mit volatile deklariert werden für
atomic read / write Zugriff
13/27
Atomic
Mit synchronized, ohne atomic:
●
●
Ohne Synchronized, mit atomic:
Atomic benutzt “compare and set” im Vergleich zum Monitor
Konzept.
Keine Locks → effektiver als synchronized!
14/27
Atomic
Auswahl Klassen:
Am Beispiel AtomicInteger:
15/27
Halbzeit!!
Im Prinzip sind wir, was Multithreading angeht, komplett. Mit
synchronized, volatile, wait(), notify(), notifyAll() können wir alles
darstellen.
Aber: Java Concurrency bietet uns viel mehr Komplexität!!!
So müssen wir aus einfachen Bausteinen “das Rad nicht immer neu
erfinden” ;)
16/27
Executors
●
●
In großen Anwendungen ist es sinnvoll Thread Erstellung und
Management von der restlichen Anwendung zu trennen.
Executor Interface
r ist Runnable Objekt
ersetze: (new Thread(r)).start();
mit: e.execute(r);
●
ExecutorService
Subinterface von Executor, mit Managementfeaturen für Lebenszyklus
der Threads und des Executors.
●
ScheduledExecutorService
Subinterface von ExecutorService, unterstützt zukünftige oder
periodische Ausführung der Tasks.
17/27
Executors - ThreadPools
●
●
●
Die meisten executor Implementationen in java.util.concurrent benutzen thread
pools, welche aus Workerthreads bestehen
Benutzung von Workerthreads minimiert Overhead von Erstellen/Löschen
Zur Instantiierung von Thread-Pools stellt Klasse Executors die folgenden Typen
bereit:
–
FixedThreadPool:
Ein Threadpool mit festgelegter Anzahl von Threads
–
CachedThreadPool:
Dynamischer Pool, dessen Threads auf Anfrage generiert und automatisch
wieder gelöscht werden, sobald einzelne Threads länger als 60 Sekunden
nicht benötigt werden
–
ScheduledThreadPool:
Threadpool dessen Threads nach einem Zeitplan oder periodisch aktiv werden
18/27
Executors – Fork/Join
●
Implementation des ExecutorService Interface; Neu in JDK 7!
●
Unterstützt Vorteil durch multiple Prozessoren
●
●
Benutzt “work-stealing” Algorithmus. Worker Threads die fertig sind,
können Aufgaben von anderen beschäftigten Workern stehlen.
Vorgehen:
1) Packe diesen Code in
ForkJoinTask Subklasse:
2) Instanziiere Objekt das alle Arbeit repräsentiert und übergebe es
der invoke() Methode einer ForkJoinPool Instanz.
19/27
Executors – Fork/Join
Vorgehen Pseudocode:
●
●
StandardImplementation: Java SE 8 benutzt in java.util.Arrays
fork/join Implementation für parallelSort() Methode
Wie sort(), aber unterstützt multiple Prozessoren für parallel Sort →
Nebenläufigkeit via fork/join framework
20/27
ConcurrentCollections
●
java.util.concurrent package hat einige Erweiterungen für das Java
Collections Framework
–
BlockingQueue:
FIFO Queue die blockiert, wenn man in eine volle Queue
hinzufügt oder aus einer leeren Queue liest
–
ConcurrentMap:
Subinterface von java.util.Map das atomare Operationen
definiert. Map Operationen (add,remove) atomar →
Synchronisierung überflüssig.
–
ConcurrentNavigableMap:
Subinterface von ConcurrentMap.
21/27
Future
●
Future repräsentiert Ergebnis einer asynchronen Berechnung.
22/27
Future
23/27
CyclicBarrier
●
Synchronisation für viele Threads, die warten müssen bis alle einen
gemeinsamen Barriere-Punkt erreicht haben
24/27
Locks
●
●
●
●
Synchronized Code hat eine einfache Form des ReentrantLock.
Diese Art des Locks ist einfach zu benutzen, hat aber viele
Einschränkungen.
Komplexere locking Eigenschaften werden unterstützt durch
java.util.concurrent.locks package
Wie bei impliziten Locks (synchronized), kann auch bei Lock
Objects nur ein Thread ein Lock Object zur Zeit besitzen. Lock
Objects unterstützen auch wait/notify durch ihre Condition Objects.
Der größte Vorteil von Lock Objects zu impliziten Locks ist ihre
Eigenschaft einen Lockingversuch abzubrechen. Die tryLock
Methode bricht ab, wenn das Lock nicht sofort frei ist, oder nach
einem timeout (wenn gewünscht).
25/27
Locks
Gleiche Funktionalität durch Lock oder synchronized:
Durch Locks mehr Freiheit, aber auch mehr zu beachten!
26/27
Quellen
[1] Java Concurrency Tutorial
http://docs.oracle.com/javase/tutorial/essential/concurrency/
[2] API Documentation
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summ
ary.html
[3] Java Concurrency Animations by Victor Grazi
http://sourceforge.net/projects/javaconcurrenta/
[4] New Concurrency Features for Java SE 7
http://www.infoq.com/news/2007/07/concurrency-java-se-7
[5] Wikipediaeintrag Java Concurrency
https://en.wikipedia.org/wiki/Java_concurrency
[6] Material der Vorlesung Parallele Programmierung
https://www.fbi.h-da.de/organisation/personen/froehlich-guenther.html
27/27