Vorwort zur 5. Auflage | 6 |
Inhalt | 10 |
1 Einleitung | 16 |
1.1 Parallelität, Nebenläufigkeit und Verteilung | 16 |
1.2 Programme, Prozesse und Threads | 17 |
2 Grundlegende Synchronisationskonzepte in Java | 21 |
2.1 Erzeugung und Start von Java-Threads | 21 |
2.1.1 Ableiten der Klasse Thread | 21 |
2.1.2 Implementieren der Schnittstelle Runnable | 23 |
2.1.3 Einige Beispiele | 26 |
2.2 Probleme beim Zugriff auf gemeinsam genutzte Objekte | 32 |
2.2.1 Erster Lösungsversuch | 36 |
2.2.2 Zweiter Lösungsversuch | 37 |
2.3 Synchronized und volatile | 39 |
2.3.1 Synchronized-Methoden | 39 |
2.3.2 Synchronized-Blöcke | 40 |
2.3.3 Wirkung von synchronized | 42 |
2.3.4 Notwendigkeit von synchronized | 43 |
2.3.5 Volatile | 44 |
2.3.6 Regel für die Nutzung von synchronized | 45 |
2.4 Ende von Java-Threads | 46 |
2.4.1 Asynchrone Beauftragung mit Abfragen der Ergebnisse | 47 |
2.4.2 Zwangsweises Beenden von Threads | 53 |
2.4.3 Asynchrone Beauftragung mit befristetem Warten | 58 |
2.4.4 Asynchrone Beauftragung mit Rückruf (Callback) | 60 |
2.4.5 Asynchrone Beauftragung mit Rekursion | 63 |
2.5 Wait und notify | 66 |
2.5.1 Erster Lösungsversuch | 67 |
2.5.2 Zweiter Lösungsversuch | 68 |
2.5.3 Dritter Lösungsversuch | 69 |
2.5.4 Korrekte und effiziente Lösung mit wait und notify | 70 |
2.6 NotifyAll | 78 |
2.6.1 Erzeuger-Verbraucher-Problem mit wait und notify | 79 |
2.6.2 Erzeuger-Verbraucher-Problem mit wait und notifyAll | 83 |
2.6.3 Faires Parkhaus mit wait und notifyAll | 85 |
2.7 Prioritäten von Threads | 87 |
2.8 Thread-Gruppen | 94 |
2.9 Vordergrund- und Hintergrund-Threads | 99 |
2.10 Weitere „gute“ und „schlechte“ Thread-Methoden | 100 |
2.11 Thread-lokale Daten | 102 |
2.12 Zusammenfassung | 104 |
3 Fortgeschrittene Synchronisationskonzepte in Java | 109 |
3.1 Semaphore | 110 |
3.1.1 Einfache Semaphore | 110 |
3.1.2 Einfache Semaphore für den gegenseitigen Ausschluss | 111 |
3.1.3 Einfache Semaphore zur Herstellung vorgegebener Ausführungsreihenfolgen | 113 |
3.1.4 Additive Semaphore | 116 |
3.1.5 Semaphorgruppen | 119 |
3.2 Message Queues | 122 |
3.2.1 Verallgemeinerung des Erzeuger-Verbraucher-Problems | 122 |
3.2.2 Übertragung des erweiterten Erzeuger-Verbraucher-Problems auf Message Queues | 124 |
3.3 Pipes | 127 |
3.4 Philosophen-Problem | 130 |
3.4.1 Lösung mit synchronized – wait – notifyAll | 131 |
3.4.2 Naive Lösung mit einfachen Semaphoren | 133 |
3.4.3 Einschränkende Lösung mit gegenseitigem Ausschluss | 135 |
3.4.4 Gute Lösung mit einfachen Semaphoren | 136 |
3.4.5 Lösung mit Semaphorgruppen | 139 |
3.5 Leser-Schreiber-Problem | 141 |
3.5.1 Lösung mit synchronized – wait – notifyAll | 142 |
3.5.2 Lösung mit additiven Semaphoren | 146 |
3.6 Schablonen zur Nutzung der Synchronisationsprimitive und Konsistenzbetrachtungen | 147 |
3.7 Concurrent-Klassenbibliothek aus Java 5 | 151 |
3.7.1 Executors | 152 |
3.7.2 Locks und Conditions | 158 |
3.7.3 Atomic-Klassen | 166 |
3.7.4 Synchronisationsklassen | 170 |
3.7.5 Queues | 173 |
3.8 Das Fork-Join-Framework von Java 7 | 174 |
3.8.1 Grenzen von ThreadPoolExecutor | 174 |
3.8.2 ForkJoinPool und RecursiveTask | 176 |
3.8.3 Beispiel zur Nutzung des Fork-Join-Frameworks | 178 |
3.9 Das Data-Streaming-Framework von Java 8 | 181 |
3.9.1 Einleitendes Beispiel | 181 |
3.9.2 Sequenzielles Data-Streaming | 183 |
3.9.3 Paralleles Data-Streaming | 187 |
3.10 Die Completable Futures von Java 8 | 188 |
3.11 Ursachen für Verklemmungen | 195 |
3.11.1 Beispiele für Verklemmungen mit synchronized | 196 |
3.11.2 Beispiele für Verklemmungen mit Semaphoren | 199 |
3.11.3 Bedingungen für das Eintreten von Verklemmungen | 200 |
3.12 Vermeidung von Verklemmungen | 201 |
3.12.1 Anforderung von Betriebsmitteln „auf einen Schlag“ | 204 |
3.12.2 Anforderung von Betriebsmitteln gemäß einer vorgegebenen Ordnung | 205 |
3.12.3 Weitere Verfahren | 206 |
3.13 Zusammenfassung | 208 |
4 Parallelität und grafische Benutzeroberflächen | 210 |
4.1 Einführung in die Programmierung grafischer Benutzeroberflächen mit JavaFX | 211 |
4.1.1 Allgemeines zu grafischen Benutzeroberflächen | 211 |
4.1.2 Erstes JavaFX-Beispiel | 212 |
4.1.3 Ereignisbehandlung | 213 |
4.2 Properties, Bindings und JavaFX-Collections | 217 |
4.2.1 Properties | 217 |
4.2.2 Bindings | 220 |
4.2.3 JavaFX-Collections | 222 |
4.3 Elemente von JavaFX | 222 |
4.3.1 Container | 222 |
4.3.2 Interaktionselemente | 225 |
4.3.3 Grafikprogrammierung | 227 |
4.3.4 Weitere Funktionen von JavaFX | 233 |
4.4 MVP | 234 |
4.4.1 Prinzip von MVP | 235 |
4.4.2 Beispiel zu MVP | 236 |
4.5 Threads und JavaFX | 243 |
4.5.1 Threads für JavaFX | 243 |
4.5.2 Länger dauernde Ereignisbehandlungen | 244 |
4.5.3 Beispiel Stoppuhr | 249 |
4.5.4 Tasks und Services in JavaFX | 255 |
4.6 Zusammenfassung | 264 |
5 Verteilte Anwendungen mit Sockets | 265 |
5.1 Einführung in das Themengebiet der Rechnernetze | 266 |
5.1.1 Schichtenmodell | 266 |
5.1.2 IP-Adressen und DNS-Namen | 270 |
5.1.3 Das Transportprotokoll UDP | 271 |
5.1.4 Das Transportprotokoll TCP | 272 |
5.2 Socket-Schnittstelle | 273 |
5.2.1 Socket-Schnittstelle zu UDP | 273 |
5.2.2 Socket-Schnittstelle zu TCP | 275 |
5.2.3 Socket-Schnittstelle für Java | 277 |
5.3 Kommunikation über UDP mit Java-Sockets | 278 |
5.4 Multicast-Kommunikation mit Java-Sockets | 287 |
5.5 Kommunikation über TCP mit Java-Sockets | 291 |
5.6 Sequenzielle und parallele Server | 301 |
5.6.1 TCP-Server mit dynamischer Parallelität | 302 |
5.6.2 TCP-Server mit statischer Parallelität | 306 |
5.6.3 Sequenzieller, „verzahnt“ arbeitender TCP-Server | 311 |
5.7 Zusammenfassung | 315 |
6 Verteilte Anwendungen mit RMI | 316 |
6.1 Prinzip von RMI | 316 |
6.2 Einführendes RMI-Beispiel | 319 |
6.2.1 Basisprogramm | 319 |
6.2.2 RMI-Client mit grafischer Benutzeroberfläche | 323 |
6.2.3 RMI-Registry | 328 |
6.3 Parallelität bei RMI-Methodenaufrufen | 332 |
6.4 Wertübergabe für Parameter und Rückgabewerte | 336 |
6.4.1 Serialisierung und Deserialisierung von Objekten | 337 |
6.4.2 Serialisierung und Deserialisierung bei RMI | 342 |
6.5 Referenzübergabe für Parameter und Rückgabewerte | 346 |
6.6 Transformation lokaler in verteilte Anwendungen | 361 |
6.6.1 Rechnergrenzen überschreitende Synchronisation mit RMI | 361 |
6.6.2 Asynchrone Kommunikation mit RMI | 364 |
6.6.3 Verteilte MVP-Anwendungen mit RMI | 365 |
6.7 Dynamisches Umschalten zwischen Wert- und Referenzübergabe – Migration von Objekten | 366 |
6.7.1 Das Exportieren und „Unexportieren“ von Objekten | 366 |
6.7.2 Migration von Objekten | 369 |
6.7.3 Eintrag eines Nicht-Stub-Objekts in die RMI-Registry | 376 |
6.8 Laden von Klassen über das Netz | 377 |
6.9 Realisierung von Stubs und Skeletons | 378 |
6.9.1 Realisierung von Skeletons | 379 |
6.9.2 Realisierung von Stubs | 379 |
6.10 Verschiedenes | 382 |
6.11 Zusammenfassung | 383 |
7 Webbasierte Anwendungen mit Servlets und JSF | 384 |
7.1 HTTP und HTML | 385 |
7.1.1 GET | 385 |
7.1.2 Formulare in HTML | 388 |
7.1.3 POST | 390 |
7.1.4 Format von HTTP-Anfragen und -Antworten | 391 |
7.2 Einführende Servlet-Beispiele | 392 |
7.2.1 Allgemeine Vorgehensweise | 392 |
7.2.2 Erstes Servlet-Beispiel | 393 |
7.2.3 Zugriff auf Formulardaten | 395 |
7.2.4 Zugriff auf die Daten der HTTP-Anfrage und -Antwort | 397 |
7.3 Parallelität bei Servlets | 398 |
7.3.1 Demonstration der Parallelität von Servlets | 398 |
7.3.2 Paralleler Zugriff auf Daten | 400 |
7.3.3 Anwendungsglobale Daten | 404 |
7.4 Sessions und Cookies | 407 |
7.4.1 Sessions | 408 |
7.4.2 Realisierung von Sessions mit Cookies | 412 |
7.4.3 Direkter Zugriff auf Cookies | 414 |
7.4.4 Servlets mit länger dauernden Aufträgen | 415 |
7.5 Asynchrone Servlets | 421 |
7.6 Filter | 425 |
7.7 Übertragung von Dateien mit Servlets | 426 |
7.7.1 Herunterladen von Dateien | 426 |
7.7.2 Hochladen von Dateien | 429 |
7.8 JSF (Java Server Faces) | 432 |
7.8.1 Einführendes Beispiel | 432 |
7.8.2 Managed Beans und deren Scopes | 439 |
7.8.3 MVP-Prinzip mit JSF | 443 |
7.8.4 AJAX mit JSF | 444 |
7.9 RESTful WebServices | 448 |
7.9.1 Definition von RESTful WebServices | 449 |
7.9.2 JSON | 450 |
7.9.3 Beispiel | 452 |
7.10 WebSockets | 457 |
7.11 Zusammenfassung | 461 |
Literatur | 464 |
Index | 466 |