Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
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?

Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren mit der Java Standard Edition Version 6
Buch: Java ist auch eine Insel

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
Pfeil 10 Threads und nebenläufige Programmierung
Pfeil 10.1 Nebenläufigkeit
Pfeil 10.1.1 Threads und Prozesse
Pfeil 10.1.2 Wie parallele Programme die Geschwindigkeit steigern können
Pfeil 10.1.3 Was Java für Nebenläufigkeit alles bietet
Pfeil 10.2 Threads erzeugen
Pfeil 10.2.1 Threads über die Schnittstelle Runnable implementieren
Pfeil 10.2.2 Thread mit Runnable starten
Pfeil 10.2.3 Der Name eines Threads
Pfeil 10.2.4 Die Klasse Thread erweitern
Pfeil 10.2.5 Wer bin ich?
Pfeil 10.3 Die Zustände eines Threads
Pfeil 10.3.1 Threads schlafen
Pfeil 10.3.2 Mit yield() auf Rechenzeit verzichten
Pfeil 10.3.3 Das Ende eines Threads
Pfeil 10.3.4 UncaughtExceptionHandler für unbehandelte Ausnahmen
Pfeil 10.3.5 Einen Thread höflich mit Interrupt beenden
Pfeil 10.3.6 Der stop() von außen und die Rettung mit ThreadDeath
Pfeil 10.3.7 Ein Rendezvous mit join()
Pfeil 10.3.8 Barrier und Austausch mit Exchanger
Pfeil 10.3.9 Arbeit niederlegen und wieder aufnehmen
Pfeil 10.3.10 Priorität
Pfeil 10.3.11 Der Thread ist ein Dämon
Pfeil 10.4 Der Ausführer (Executor) kommt
Pfeil 10.4.1 Die Schnittstelle Executor
Pfeil 10.4.2 Die Thread-Pools
Pfeil 10.4.3 Threads mit Rückgabe über Callable
Pfeil 10.4.4 Mehrere Callable abarbeiten
Pfeil 10.4.5 Mit ScheduledExecutorService wiederholende Ausgaben und Zeitsteuerungen
Pfeil 10.5 Synchronisation über kritische Abschnitte
Pfeil 10.5.1 Gemeinsam genutzte Daten
Pfeil 10.5.2 Probleme beim gemeinsamen Zugriff und kritische Abschnitte
Pfeil 10.5.3 Punkte parallel initialisieren
Pfeil 10.5.4 i++ sieht atomar aus, ist es aber nicht
Pfeil 10.5.5 Kritische Abschnitte schützen
Pfeil 10.5.6 Schützen mit ReentrantLock
Pfeil 10.5.7 Synchronisieren mit synchronized
Pfeil 10.5.8 Synchronized-Methoden der Klasse StringBuffer
Pfeil 10.5.9 Mit synchronized synchronisierte Blöcke
Pfeil 10.5.10 Dann machen wir doch gleich alles synchronisiert!
Pfeil 10.5.11 Lock-Freigabe im Fall von Exceptions
Pfeil 10.5.12 Mit synchronized nachträglich synchronisieren
Pfeil 10.5.13 Monitore sind reentrant – gut für die Geschwindigkeit
Pfeil 10.5.14 Synchronisierte Methodenaufrufe zusammenfassen
Pfeil 10.5.15 Deadlocks
Pfeil 10.6 Synchronisation über Warten und Benachrichtigen
Pfeil 10.6.1 Die Schnittstelle Condition
Pfeil 10.6.2 Beispiel: Erzeuger-Verbraucher-Programm
Pfeil 10.6.3 Warten mit wait() und Aufwecken mit notify()
Pfeil 10.6.4 Falls der Lock fehlt: IllegalMonitorStateException
Pfeil 10.6.5 Semaphor
Pfeil 10.7 Atomare Operationen und frische Werte mit volatile
Pfeil 10.7.1 Der Modifizierer volatile bei Objekt-/Klassenvariablen
Pfeil 10.7.2 Das Paket java.util.concurrent.atomic
Pfeil 10.8 Mit dem Thread verbundene Variablen
Pfeil 10.8.1 ThreadLocal
Pfeil 10.8.2 InheritableThreadLocal
Pfeil 10.9 Gruppen von Threads in einer Thread-Gruppe
Pfeil 10.9.1 Aktive Threads in der Umgebung
Pfeil 10.9.2 Etwas über die aktuelle Thread-Gruppe herausfinden
Pfeil 10.9.3 Threads in einer Thread-Gruppe anlegen
Pfeil 10.9.4 Methoden von Thread und ThreadGroup im Vergleich
Pfeil 10.10 Zeitgesteuerte Abläufe
Pfeil 10.10.1 Die Klassen Timer und TimerTask
Pfeil 10.10.2 Job-Scheduler Quartz
Pfeil 10.11 Einen Abbruch der virtuellen Maschine erkennen
Pfeil 10.12 Zum Weiterlesen


Galileo Computing - Zum Seitenanfang

10.8 Mit dem Thread verbundene Variablen Zur nächsten ÜberschriftZur vorigen Überschrift

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.


Galileo Computing - Zum Seitenanfang

10.8.1 ThreadLocal Zur nächsten ÜberschriftZur vorigen Überschrift

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.


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

Galileo Computing - Zum Seitenanfang

10.8.2 InheritableThreadLocal topZur vorigen Überschrift

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.






<< zurück



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