Nebenläufige Programmierung mit Threads

Anlegen von Threads

Threads erzeugen

Implementiere ein Thread-Beispiel und erzeuge in main(...) neue 100 Threads. Die run()-Methode jedes Threads soll dabei die Thread-ID in einer Endlosschleife mittels System.out.println(Thread.currentThread().getId()); anzeigen. Wir erhalten dann auf dem Bildschirm Meldungen der Art

1
2
1
2
3
2

Wie viele Threads lassen sich erzeugen, bis das System "steht"? Beobachte den Speicherverbrauch unter dem Task-Manager (Alt/Ctrl/Del) an. Lässt sich abschätzen, was ein Thread "kostet"?

Lösung

Thread-Eigenschaften

Threads schlafen

Das unter Unix bekannte Programm sleep kann man auf der Kommandozeile aufrufen und es schläft dann eine Zeit lang.

  1. Implementiere das Programm in Java, sodass man auf der Kommandozeile schreiben kann:
    $ java Sleep 22
    Dann soll das Programm 22 Sekunden schlafen.
  2. Jetzt sollen nicht nur Sekunden verwendet werden. Erweitere das Programm, sodass ein zweites Argument auch Minuten, Stunden oder Tage wartet. Wirf für die Schreibweise einen Blick in das C-Programm.

Lösung

Dämonen

Implementiere einen java.lang.Thread in einer Endlosschleife. Er soll jede Sekunde eine Meldung wie etwa "Hallo" auf dem Bildschirm ausgeben. Markiere den Thread einmal als Dämon und einmal nicht.

Lösung

Threads beobachten Dateien *

Schreibe eine Klasse DateiBeobachter mit einem Konstruktor DateiBeobachter(String) und DateiBeobachter(java.io.File). Die Klasse soll beobachten, ob sich eine Datei im Dateisystem ändert.

Lösung

Threads unterbrechen *

Man kann einen Thread mit der stop()-Methode unterbrechen, doch so gibt man ihm keine Chance, sich ordentlich zu beenden. Daher kann man einen Interrupt senden, der ein Flag setzt, der in der run()-Methode abgefragt werden kann. Schreibe ein Programm, welches sich in einer Endlosschleife befindet. Reagiere auf einen Abbruch von außen. Lese aus java.lang.Thread die Beschreibung zu den Methoden isInterrupted() und interrupt().

Ein Timer-Label *

Klasse Uhrzeit, der Frame
Klasse TimeLabel

Exceptions auffangen (25 Minuten)

Implementiere einen Thread, der durch die Division mit Null eine Exception wirft. Fange den Fehlerfall dieses speziellen Threads durch einen UncaughtExceptionHandler ab.

Lösung

Executor

 Thread-Pool (20 Minuten)

Erzeuge mit ExecutorService s = Executors.newCachedThreadPool(); einen java.util.concurrent.ExecutorService und führe mit s.execute(...) Programmcode vom folgenden Kern in run() aus java.lang.Runnable aus:

class MyRunnable implements Runnable
{
  public void run()
  {
    System.out.println( Thread.currentThread() );
//  try {
//   Thread.sleep( 1000 );
//  } catch ( InterruptedException e ) {
//   e.printStackTrace();
//  }
  }
}

Das Programm sieht dann so aus:

ExecutorService s = Executors.newCachedThreadPool();
Runnable run = new MyRunnable();
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
...

Welchen Unterschied macht es, ob man die Zeilen auskommentiert oder wieder in den Programmfluss integriert?

Kommt Zeit kommt Runnable

Nutzte den ScheduledExecutorService zum Arbeiten von Programmteilen.

Wie kann man die Abarbeitung etwa nach ein paar Sekunden beenden?

Synchronisation

Motivation für Synchronisierung *

Schreibe ein Runnable, was in einen StringBuffer 100 mal Thread.currentThread().toString() anhängt. Starte drei Threads, die sich alle den gleichen StringBuffer teilen, ihn also als gemeinsame Ressource nutzen. Ändere StringBuffer in StringBuilder und beobachte das Ergebnis.

Lösung

Thread-Kooperation und Benachrichtigung

Schere, Papier, Stein

Zwei Threads sollen auf ein Signal warten, das von einem dritten Threads jede Sekunde gesendet wird. Kommt das Signal, soll sich der erste und zweite Thread zufällig für Schere, Papier oder Stein entscheiden.