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