Previous Contents Next

10   Threads

Inhalt Threads ·Zustände von Threads ·Synchronisation ·Prioritäten ·Threadgroups
Literatur: [Fla99b] gibt diesmal nicht soviel her, zumindest nicht auf einem Fleck konzentriert. In [LL97] werden Threads in Abschnitt 14.2 besprochen. Der entsprechende Abschnitt in Suns Javatutorial [CW96] ist ebenfalls recht brauchbar. Daneben gibt es natürlich noch [OW97] nur über Threads in Java, aber ich kenne es nicht selbst. Auch in [Lea99] findet sich eine sehr empfehlenswerte Beschreibung von Synchronisation in Java, auch in einem größeren Kontext (insbesondere Abschnitt 2.2 für Locking). In der Klassenbibliothek sind java.lang.Thread und java.lang.ThreadGroup die wichtigsten Klassen zum Thema.
Allgemeines


Threads in Java
Beispiel 23  [ Unterklasse von Thread]   Die Klasse erweitert einfach Threads und überschreibt die run-Methode.

public class SimpleThread extends Thread {
  public SimpleThread(String str) {
    super(str);
  }
  public void run() {              // "uberschreiben
    for (int i = 0; i < 10; i++) {
      System.out.println(i + " " + getName());
      try {
        sleep((int)(Math.random() * 1000));
      } catch (InterruptedException e) {}
    }
    System.out.println("DONE! " + getName());
  }
};


Beispiel 24  [ Implementieren von Runnable]   Dies ist die zweite Möglichkeit, wie man einen Thread bekommen kann. Der Konstruktor der Thread-Klasse macht aus einem Objekt, das ein Runnable-Interface implementiert, den eigentlichen Thread. Dieser muß dann extra gestartet werden. Das starten wiederum ruft run auf.

import java.awt.Graphics;
import java.util.*;
import java.text.DateFormat;
import java.applet.Applet;

public class Clock extends Applet implements Runnable {
  private Thread clockThread = null;

  public void start() {
    if (clockThread == null) {
      clockThread = new Thread(this, "Clock");  // Konstuktor Thread
      clockThread.start();
    }
  }
  public void run() {                   // wg. Interface runnable
    Thread myThread = Thread.currentThread();
      while (clockThread == myThread) {
        repaint();
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e){}
      }
  }
  public void paint(Graphics g) {
    Calendar cal = Calendar.getInstance();
    Date date = cal.getTime();
    DateFormat dateFormatter = DateFormat.getTimeInstance();
    g.drawString(dateFormatter.format(date), 5, 10);
  }

  public void stop() {                // Applets stop Methode
    clockThread = null;
  }
};


Zustände von Threads


Lebenszyklus eines Threads


Hier eine Zusammenfassung der Zustände und Übergänge von Threads:



Synchronisation


Beispiel 25  [Leser/Schreiber]   In folgendem Scenario haben die Objekte Schreiber und Leser Zugriff auf dasselbe Speicherobjekt, der eine schreibend, der andere lesend. Das Speicherobjekt soll einfach eine Speicherzelle darstellen, auf die mit den Methoden get und put zugegriffen wird. Es gibt zwei Dinge zu koordinieren:

Gegenseitiger Ausschluss (synchronized)


Beispiel 26  [Leser/Schreiber (2)]   Da im Leser/Schreiber-Beispiel mittels der beiden Zugriffsmethoden get und put auf die gemeinsamen Daten zugegriffen werden soll, kann man den gleichzeitigen Zugriff dadurch verbieten, dass man die Methoden als synchronized markiert.


public class Speicher {      // Speicher muß kein Thread sein
  private int speicherzelle  // das gemeinsame Datum
  
  public synchronized int get () {
    ....
    };


  public synchronized void put (int value) {
    ....

    };
};

Warten auf Nachricht


Beispiel 27  [Leser/Schreiber (3)]   In dem Leser/Schreiber-Beispiel kann man diese Methoden verwenden, um die Geschwindigkeit der Threads anzugleichen.

public synchronized int get() {
  while (available == false) {   // Explizite Schleife
    try {
      wait();       // Warten auf den Schreiber
      } catch (InterruptedException e) {
      }
    }
  available = false;
  notifyAll();     // Benachrichtigen
  return contents;
  }

public synchronized void put(int value) {
  while (available == true) {
    try {
      wait();     // Warten auf den Leser
      } catch (InterruptedException e) {
      }
    }
  contents = value;
  available = true;
  notifyAll();    // Benachrichtigen
  } 

Sonstige Interaktion mit Threads
Alternative zum Suspendieren


Beispiel 28  [Suspendieren]   Folgendes Beispiel zeigt, wie man die Methoden suspend und resume umgehen kann, indem man wait und notify und ein Flag (hier suspended verwendet. An Stelle von suspend und resume treten Methoden mySuspend und myResume. Das Flag schaltet den suspend-Zustand ein und aus. Das wait muß synchronisiert sein.



import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Suspend extends Applet {
  private TextField t = new TextField(10); // output
  private Button                           // zwei Kn"opfe
    suspendbutton = new Button("Suspend"),
    resumebutton  = new Button("Resume");

  public class Suspendable extends Thread {
    private int count =0;
    private boolean suspended = false;     // Flag
    public Suspendable (){ start();};
    
    public void mySuspend() {
      suspended = true;                    // Flag => true
    };
    public synchronized void myResume(){
      suspended = false;                   // Flag => false
      notify();
    };
    
    public void run() {                    // Runnable
      while (true) {
 try {
   sleep(100);
   synchronized(this) {           // auf sich selbst
     while  (suspended) wait();   // sync-Block
   }
 }  catch (InterruptedException e){};
 t.setText(Integer.toString(count++));
      };
    };
  };

  private Suspendable ss = new Suspendable();

  public void init() {                    // Applet
    add(t);

    suspendbutton.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
 ss.mySuspend();
      }
    });
    resumebutton.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
 ss.myResume();
      }
    });
    add(suspendbutton);                    // Kn"opfe ans 
    add(resumebutton);                     // Applet heften
  };                                       // Ende init

  public static void main(String[] args) { // stand-alone
    Suspend applet   = new Suspend();
    Frame   aFrame   = new Frame("Suspend");
    aFrame.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
 System.exit(0);                    // ordentlich 
      };                                   // terminieren
    });
    
    aFrame.add(applet, BorderLayout.CENTER);
    aFrame.setSize(300, 300);
    applet.init();
    applet.start();                       // thread starten
    aFrame.setVisible(true);              // = show
  };
};
         

          
     
    
  
  


Prioritäten


Gruppen von Threads



?


July 4, 2000
Previous Contents Next