Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Java ist auch eine Sprache
2 Sprachbeschreibung
3 Klassen und Objekte
4 Der Umgang mit Zeichenketten
5 Mathematisches
6 Eigene Klassen schreiben
7 Angewandte Objektorientierung
8 Exceptions
9 Die Funktionsbibliothek
10 Threads und nebenläufige Programmierung
11 Raum und Zeit
12 Datenstrukturen und Algorithmen
13 Dateien und Datenströme
14 Die eXtensible Markup Language (XML)
15 Grafische Oberflächen mit Swing
16 Grafikprogrammierung
17 Netzwerkprogrammierung
18 Verteilte Programmierung mit RMI und Web-Services
19 JavaServer Pages und Servlets
20 Applets
21 Midlets und die Java ME
22 Datenbankmanagement mit JDBC
23 Reflection und Annotationen
24 Logging und Monitoring
25 Sicherheitskonzepte
26 Java Native Interface (JNI)
27 Dienstprogramme für die Java-Umgebung
A Die Begleit-DVD
Stichwort
Download: - ZIP, ca. 12,5 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> /Java-Insel | vor >>
Java ist auch eine Insel von Christian Ullenboom Programmieren mit der Java Standard Edition Version 6
Java ist auch eine Insel 7., aktualisierte Auflage geb., mit DVD (November 2007) 1.492 S., 49,90 Euro Galileo Computing ISBN 978-3-8362-1146-8 |
| 10 Threads und nebenläufige Programmierung
|  | 10.1 Nebenläufigkeit
|  |  | 10.1.1 Threads und Prozesse
|  |  | 10.1.2 Wie parallele Programme die Geschwindigkeit steigern können
|  |  | 10.1.3 Was Java für Nebenläufigkeit alles bietet
|  | 10.2 Threads erzeugen
|  |  | 10.2.1 Threads über die Schnittstelle Runnable implementieren
|  |  | 10.2.2 Thread mit Runnable starten
|  |  | 10.2.3 Der Name eines Threads
|  |  | 10.2.4 Die Klasse Thread erweitern
|  |  | 10.2.5 Wer bin ich?
|  | 10.3 Die Zustände eines Threads
|  |  | 10.3.1 Threads schlafen
|  |  | 10.3.2 Mit yield() auf Rechenzeit verzichten
|  |  | 10.3.3 Das Ende eines Threads
|  |  | 10.3.4 UncaughtExceptionHandler für unbehandelte Ausnahmen
|  |  | 10.3.5 Einen Thread höflich mit Interrupt beenden
|  |  | 10.3.6 Der stop() von außen und die Rettung mit ThreadDeath
|  |  | 10.3.7 Ein Rendezvous mit join()
|  |  | 10.3.8 Barrier und Austausch mit Exchanger
|  |  | 10.3.9 Arbeit niederlegen und wieder aufnehmen
|  |  | 10.3.10 Priorität
|  |  | 10.3.11 Der Thread ist ein Dämon
|  | 10.4 Der Ausführer (Executor) kommt
|  |  | 10.4.1 Die Schnittstelle Executor
|  |  | 10.4.2 Die Thread-Pools
|  |  | 10.4.3 Threads mit Rückgabe über Callable
|  |  | 10.4.4 Mehrere Callable abarbeiten
|  |  | 10.4.5 Mit ScheduledExecutorService wiederholende Ausgaben und Zeitsteuerungen
|  | 10.5 Synchronisation über kritische Abschnitte
|  |  | 10.5.1 Gemeinsam genutzte Daten
|  |  | 10.5.2 Probleme beim gemeinsamen Zugriff und kritische Abschnitte
|  |  | 10.5.3 Punkte parallel initialisieren
|  |  | 10.5.4 i++ sieht atomar aus, ist es aber nicht
|  |  | 10.5.5 Kritische Abschnitte schützen
|  |  | 10.5.6 Schützen mit ReentrantLock
|  |  | 10.5.7 Synchronisieren mit synchronized
|  |  | 10.5.8 Synchronized-Methoden der Klasse StringBuffer
|  |  | 10.5.9 Mit synchronized synchronisierte Blöcke
|  |  | 10.5.10 Dann machen wir doch gleich alles synchronisiert!
|  |  | 10.5.11 Lock-Freigabe im Fall von Exceptions
|  |  | 10.5.12 Mit synchronized nachträglich synchronisieren
|  |  | 10.5.13 Monitore sind reentrant – gut für die Geschwindigkeit
|  |  | 10.5.14 Synchronisierte Methodenaufrufe zusammenfassen
|  |  | 10.5.15 Deadlocks
|  | 10.6 Synchronisation über Warten und Benachrichtigen
|  |  | 10.6.1 Die Schnittstelle Condition
|  |  | 10.6.2 Beispiel: Erzeuger-Verbraucher-Programm
|  |  | 10.6.3 Warten mit wait() und Aufwecken mit notify()
|  |  | 10.6.4 Falls der Lock fehlt: IllegalMonitorStateException
|  |  | 10.6.5 Semaphor
|  | 10.7 Atomare Operationen und frische Werte mit volatile
|  |  | 10.7.1 Der Modifizierer volatile bei Objekt-/Klassenvariablen
|  |  | 10.7.2 Das Paket java.util.concurrent.atomic
|  | 10.8 Mit dem Thread verbundene Variablen
|  |  | 10.8.1 ThreadLocal
|  |  | 10.8.2 InheritableThreadLocal
|  | 10.9 Gruppen von Threads in einer Thread-Gruppe
|  |  | 10.9.1 Aktive Threads in der Umgebung
|  |  | 10.9.2 Etwas über die aktuelle Thread-Gruppe herausfinden
|  |  | 10.9.3 Threads in einer Thread-Gruppe anlegen
|  |  | 10.9.4 Methoden von Thread und ThreadGroup im Vergleich
|  | 10.10 Zeitgesteuerte Abläufe
|  |  | 10.10.1 Die Klassen Timer und TimerTask
|  |  | 10.10.2 Job-Scheduler Quartz
|  | 10.11 Einen Abbruch der virtuellen Maschine erkennen
|  | 10.12 Zum Weiterlesen
## 10.8 Mit dem Thread verbundene Variablen Unterschiedliche Threads können ohne Probleme das gleiche Runnable ausführen, was auch ein übliches Szenario ist, wenn der Programmcode immer der gleiche ist. Doch auch wenn der Programmcode immer gleich bleibt, soll jedem Thread doch vielleicht ein eigener Speicherbereich zugeteilt werden, in dem er Informationen ablegen kann. Falls das Runnable-Objekt selbst eine Objektvariable hätte und pro Thread auf diese Weise ein neues Runnable-Objekt gebildet würde, wäre das kein Problem, doch müsste bei genau einem Runnable-Objekt und beliebig vielen Threads ein anderer Ort gefunden werden. ### 10.8.1 ThreadLocal Die Lösung ist relativ einfach: Es müsste eine Datenstruktur geben, die jeden Current-Thread mit einem Objekt assoziiert. Diese Struktur muss dann im Runnable-Objekt referenzierbar sein. Java bietet mit der Klasse java.lang.ThreadLocal eine Implementierung für thread-lokale Variablen (engl. thread local storage (TLS)) an. Hier klicken, um das Bild zu vergrößern
class java.lang.ThreadLocal<T>
ThreadLocal() Erzeugt eine neue Thread-lokale Variable. void set( T value ) Setzt den Wert für den lokalen Thread. T get() Liefert den Wert, der mit dem aktuellen Thread verbunden ist. protected T initialValue() Die Methode kann überschrieben werden und liefert dann den Anfangswert beim ersten Aufruf von get() ohne vorangehendes set(). Der Standard ist null. void remove() Entfernt den Wert der Thread-lokalen Variable, um etwa Speicher freizumachen. Ein anschließendes get() liefert wieder den Wert aus initialValue(). #### Zählen mit thread-lokalen Variablen Das folgende Beispiel soll ein Runnable definieren, das endlos zählt. Der Clou ist aber, dass der Zähler keine lokale Variable, sondern eine Thread-lokale Variable ist, die ThreadLocal verwaltet. Drei Threads sollen das gleiche Runnable abarbeiten: zwei neue Threads und der aktuell ausführende main-Thread. Listing 10.30 com/tutego/insel/thread/ThreadLocalDemo.java
    package com.tutego.insel.thread;

    public class ThreadLocalDemo
    {
      public static void main( String[] args )
      {
        Runnable runnable = new SimpleRunnable();
        new Thread( runnable ).start();
        new Thread( runnable ).start();
        runnable.run();
      }
    }

    class SimpleRunnable implements Runnable
    {
      private static final ThreadLocal<Integer> mem = new ThreadLocal<Integer>()
      {
        @Override protected Integer initialValue() { return 1; }
      };

      public void run()
      {
        while ( true )
        {
          System.out.println( Thread.currentThread().getName() +
                              ", " + mem.get() );
          mem.set( mem.get() + 1 );
        }
      }
    }
Den Startwert legt die überschriebene Methode initialValue() mit 1 fest. Da ThreadLocal einen Zähler speichert, ist der Datencontainer mit Integer typisiert. Die Ausgabe kann beginnen mit:
    main, 1
    main, 2
    main, 3
    main, 4
    main, 5
    Thread-0, 1
    Thread-1, 1
    Thread-0, 2
    Thread-1, 2
    Thread-0, 3
    Thread-1, 3
### 10.8.2 InheritableThreadLocal Jeder Thread kann einen neuen Thread bilden, der dann Kind ist. Da die main-Methode selbst von einem Haupt-Thread ausgeführt wird, wie das Beispiel zeigt, ist schon dieser Thread der Vater, der neue Unter-Threads bildet. Mit der Klasse InheritableThreadLocal, die Unterklasse von ThreadLocal ist, kann das Kind vom Vater den gespeicherten Wert übernehmen. Das würde sonst nicht funktionieren, da der neue Thread ja ganz eigene Werte hat, aber mit InheritableThreadLocal bleibt dieser Wert erhalten und wird auf die Kinder vererbt. Dass ein gestarteter Kind-Thread den Wert vom Vater-Thread übernimmt, zeigt das folgende Programm. Ein Thread gibt den geerbten Wert aus und setzt anschließend einen neuen Wert für ein Kind, das der Thread in die Welt entlässt. Listing 10.31 com/tutego/insel/thread/InheritableThreadLocalDemo.java
    package com.tutego.insel.thread;

    public class InheritableThreadLocalDemo
    {
      public static void main( String[] args )
      {
        new InheritingThread().start();
      }
    }

    class InheritingThread extends Thread
    {
    //  private static final ThreadLocal<String> mem = new ThreadLocal<String>();
      private static final InheritableThreadLocal<String> mem =
                                  new InheritableThreadLocal<String>();

      @Override public void run()
      {
        System.out.println( Thread.currentThread() + " bekommt " + mem.get() );
        mem.set( Thread.currentThread().getName() );

        new InheritingThread().start();
      }
    }
Die Ausgabe beginnt mit:
    Thread[Thread-0,5,main] bekommt null
    Thread[Thread-1,5,main] bekommt Thread-0
    Thread[Thread-2,5,main] bekommt Thread-1
    Thread[Thread-3,5,main] bekommt Thread-2
Der erste Thread bekommt noch nichts von seinem Vater-Thread. Da jedoch der erste Thread den eigenen Namen in den Speicher von InheritableThreadLocal legt und dann der zweite neu gestartete Kind-Thread auf den Wert zugreift, empfängt er die Zeichenfolge Thread-0. Wer zum Testen InheritableThreadLocal durch ThreadLocal ersetzt, wird merken, dass das Beispiel so nicht funktioniert. #### ThreadLocal bei der Performance-Optimierung Ein ThreadLocal ist eine schöne Klasse zur Performance-Optimierung. Sollen zum Beispiel zwei Threads große Datenmengen über einen zentralen Puffer lesen, müssten sie an diesem Puffer synchronisiert werden. Mit ThreadLocal kann je ein Puffer beim Thread gespeichert sein, und die Synchronisation kann entfallen. Da es im Allgemeinen wenige Threads gibt, ist die Anzahl paralleler Puffer klein. Performance-Interessierte können einen Blick auf StringCoding werfen, wie sie ThreadLocal beim Caching von (De)kodierer-Objekten nutzt. Die Klasse String nutzt StringCoding bei der Byte/Zeichen-Kodierung. Verschweigen dürfen wir aber nicht, dass der Zugriff auch etwas kostet, so dass ein kleiner synchronisierter Bereich durchaus schneller sein kann. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.
Name |
E-Mail |
Ihr Kommentar |
<< zurück | <top> | vor >>

Copyright © Galileo Press 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de