Vorwort | 5 |
Inhaltsverzeichnis | 9 |
Einführung | 15 |
Dimensionen der Parallelität | 15 |
Parallelität und Nebenläufigkeit | 16 |
Die Vorteile von Nebenläufigkeit | 17 |
Die Nachteile von Nebenläufigkeit | 17 |
Sicherer Umgang mit Nebenläufigkeit | 18 |
Maße für die Parallelisierung | 18 |
Die Gesetze von Amdahl und Gustafson | 18 |
Work-Span-Analyse | 20 |
Parallelitätsmodelle | 21 |
I Grundlegende Konzepte | 23 |
Das Thread-Konzept von Java | 25 |
Der main-Thread | 25 |
Erzeugung und Starten von Threads | 26 |
Thread-Erzeugung durch Vererbung | 27 |
Thread-Erzeugung mit Runnable-Objekten | 30 |
Der Lebenszyklus von Threads | 33 |
Beendigung eines Threads | 34 |
Auf das Ende eines Threads warten | 35 |
Aktives Beenden von Threads | 35 |
Unterbrechung mit interrupt | 38 |
Thread-Zustände | 40 |
Weitere Eigenschaften eines Thread-Objekts | 41 |
Thread-Priorität | 41 |
Daemon-Eigenschaft | 42 |
Exception-Handler | 43 |
Zusammenfassung | 45 |
Konkurrierende Zugriffe auf Daten | 47 |
Ein einleitendes Beispiel | 47 |
Java-Speichermodell | 48 |
Stacks und Heap | 49 |
Speicher auf der Hardwareebene | 51 |
Probleme mit gemeinsam nutzbaren Daten | 52 |
Sequenzielle Konsistenz | 53 |
Thread-sichere Daten und unveränderliche Objekte | 55 |
Unveränderbare Objekte | 56 |
Volatile-Attribute | 57 |
Final-Attributte | 59 |
Thread-lokale Daten | 60 |
Fallstricke | 63 |
Zusammenfassung | 64 |
Elementare Synchronisationsmechanismen | 65 |
Schlüsselwort synchronized | 65 |
Synchronized-Methoden | 65 |
Synchronized-Blöcke | 67 |
Beispiel: Thread-sicheres Singleton | 68 |
Monitorkonzept bei Java | 70 |
Fallstricke | 71 |
Zusammenfassung | 76 |
Grundlegende Thread-Steuerung | 77 |
Bedingungsvariablen und Signalisieren | 77 |
Regeln zum Umgang mit wait, notify und notifyAll | 83 |
Zusammenfassung | 86 |
II Weiterführende Konzepte | 87 |
Threadpools | 89 |
Das Poolkonzept und die Klasse Executors | 89 |
Executors mit eigener ThreadFactory | 92 |
Explizite ThreadPoolExecutor-Erzeugung | 92 |
Benutzerdefinierter ThreadPoolExecutor | 93 |
Future- und Callable-Schnittstelle | 94 |
Callable, Future und FutureTask | 95 |
Callable, Future und ExecutorService | 95 |
Callable und ThreadPoolExecutor | 98 |
Callable und ScheduledThreadPoolExecutor | 102 |
Callable und ForkJoinPool | 102 |
Exception-Handling | 104 |
Tipps für das Arbeiten mit Threadpools | 106 |
Zusammenfassung | 107 |
Atomic-Variablen | 109 |
Compare-and-Set-Operation | 110 |
Umgang mit Atomic-Variablen | 111 |
Atomic-Skalare | 111 |
Atomic-Referenzen | 114 |
Accumulator und Adder in Java 8 | 116 |
Zusammenfassung | 118 |
Lock-Objekte und Semaphore | 119 |
Lock-Objekte | 120 |
Das Lock-Interface | 120 |
ReentrantLock | 123 |
Das Condition-Interface | 125 |
ReadWriteLock | 129 |
StampedLock | 131 |
Semaphore | 134 |
Zusammenfassung | 137 |
Thread-sichere Container | 139 |
Collection-Typen | 139 |
Thread-sichere Collections | 141 |
Synchronisierte Collections | 141 |
Unmodifiable Collections | 143 |
Concurrent Collections | 144 |
Zusammenfassung | 149 |
III Ergänzende Synchronisationsmechanismen | 151 |
Exchanger und BlockingQueue | 153 |
Exchanger | 153 |
Queues | 157 |
Das Erzeuger-Verbraucher-Muster | 160 |
Varianten | 163 |
Pipeline von Erzeugern und Verbrauchern | 163 |
Erzeuger-Verbraucher-Muster mit Empfangsbestätigung | 164 |
Erzeuger-Verbraucher-Muster mit Work-Stealing | 165 |
Zusammenfassung | 171 |
CountDownLatch und CyclicBarrier | 173 |
CountDownLatch | 173 |
CyclicBarrier | 176 |
Zusammenfassung | 181 |
Phaser | 183 |
Das Konzept des Phasers | 183 |
Phaser als CountDownLatch | 184 |
Phaser als CyclicBarrier | 187 |
Phaser als variable Barriere | 188 |
Zusammenspiel mit dem ForkJoin-Threadpool | 192 |
Zusammenfassung | 193 |
IV Parallelisierungsframeworks | 195 |
Das ForkJoin-Framework | 197 |
Grundprinzip des ForkJoin-Patterns | 197 |
Programmiermodell | 198 |
Einsatz von RecursiveAction | 200 |
Einsatz von RecursiveTask | 203 |
Einsatz von CountedCompleter | 205 |
Work-Stealing-Verfahren | 208 |
Zusammenfassung | 211 |
Parallele Array- und Stream-Verarbeitung | 213 |
Parallele Array-Verarbeitung | 213 |
Parallele Transformation | 213 |
Paralleles Sortieren | 214 |
Parallele Präfixbildung | 215 |
Funktionsprinzip der Stream-Verarbeitung | 217 |
Funktionale Interfaces | 218 |
Erzeugung von Streams | 219 |
Transformations- und Manipulationsoperationen | 222 |
Auswertungen von Streams | 225 |
Eigenschaften und Operationsoptimierung | 230 |
Parallele Stream-Verarbeitung: Datenparallelität | 231 |
Arbeitsweise und korrekte Benutzung | 232 |
Parallele Reduzierer | 234 |
Parallele Collectoren | 237 |
Funktionsweise von Spliteratoren | 242 |
Benutzerdefinierte Spliteratoren | 244 |
Zusammenfassung | 249 |
CompletableFuture | 251 |
CompletableFuture als Erweiterung des Future-Patterns | 251 |
Design von asynchronen APIs | 255 |
Asynchrone APIs mit Future | 256 |
Asynchrone APIs mit CompletableFuture | 256 |
Asynchrone Verarbeitung: Task-Parallelität | 258 |
Das Starten einer asynchronen Verarbeitung | 258 |
Definition einer asynchronen Verarbeitungskette | 259 |
Das Arbeiten mit CompletableFutures | 261 |
Das Konzept des CompletionStage | 262 |
Lineare Kompositionsmöglichkeiten | 263 |
Verzweigen und Vereinen | 266 |
Synchronisationsbarrieren | 270 |
Fehlerbehandlung und Abbruch einer Verarbeitung | 271 |
Zusammenfassung | 273 |
V Fallbeispiele | 275 |
Asynchrones Logging | 277 |
Lösung mit Thread-lokalen Daten | 278 |
Verbesserte Version (Exchanger) | 280 |
Datenstrukturen in Multithreaded-Umgebungen | 285 |
Liste als sortierte Menge | 285 |
Blockierende Lösungen (Locks) | 290 |
Grobgranulare Synchronisierung | 290 |
Feingranulare Synchronisierung | 290 |
Optimistische Synchronisierung | 293 |
Lockfreie Lösung (AtomicMarkableReference) | 294 |
The Dining Philosophers Problem | 301 |
Basisalgorithmus | 302 |
Lösungsvarianten (Semaphore und Lock) | 302 |
Lösung mit einem Semaphor | 303 |
Lösung mit asymmetrischer Lock-Anforderung | 304 |
Lösung mithilfe eines Koordinators | 305 |
Lösung mit asymmetrischer Wait-Release-Strategie | 307 |
Minimal aufspannende Bäume | 309 |
Graphen und Spannbäume | 309 |
Der Prim-Algorithmus | 311 |
Funktionsweise des Algorithmus | 311 |
Implementierung des Algorithmus | 313 |
Parallelisierung (Phaser) | 315 |
Mergesort | 319 |
Funktionsprinzip des Algorithmus | 319 |
Parallelisierung (ForkJoin-Framework) | 321 |
Der k-Mean-Clusteralgorithmus | 323 |
Der k-Mean-Algorithmus | 323 |
Parallelisierung (Parallel Streams) | 325 |
Datenmodell | 325 |
Hilfsmethoden | 325 |
Implementierung | 326 |
Variante mit benutzerdefiniertem Collector | 330 |
RSA-Schlüsselerzeugung | 335 |
Verfahren für die Schlüsselerzeugung | 335 |
Parallelisierung (CompletableFuture) | 337 |
Threads bei JavaFX | 341 |
Ein einfaches Beispiel | 341 |
JavaFX-Concurrent-API | 343 |
Handler-Konzept bei Android | 349 |
UI-Thread und nebenläufige Aktivitäten | 349 |
Messages, Message-Queue, Looper | 350 |
Handler | 352 |
Aktoren | 355 |
Aktorenmodell | 355 |
Beispielimplementierung mit Akka | 356 |
Nachrichten | 357 |
Beteiligte Aktoren | 359 |
Starten der Anwendung | 361 |
VI Anhang | 363 |
Ausblick auf Java 9 | 365 |
Die Flow-Interfaces | 365 |
Literaturverzeichnis | 371 |
Index | 371 |
www.dpunkt.de | 0 |