Implementiere ein Thread-Beispiel und erzeuge in main()
100 Threads.
Die run()
-Methode soll dabei lediglich die laufende Threadnummer 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"?
Das unter Unix bekannte Programm sleep kann man auf der Kommandozeile aufrufen und es schläft dann eine Zeit lang.
$ java Sleep 22Dann soll das Programm 22 Sekunden schlafen.
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.
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.
lastModified()
, ob sich die Datei geändert hat.
Gib eine Meldung aus, wenn sich die Datei ändert. Erweiterung:
Man möchte nun flexibler auf Änderungen reagieren.
Dazu soll im Konstruktor ein
java.lang.Runnable-Objekt übergeben werden können. Dies soll sich DateiBeobachter
merken
und immer dann die run()
-Methode aufrufen, wenn sich etwas ändert.
So können wir ein Objekt anmelden, das bei einer Dateiänderung informiert wird.
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()
.
Schreibe eine eigene Klasse ThreadCollection
mit einer Funktion
createThread( String name, Runnable run)
, die einen Thread run startet
und in einen Assoziativspeicher legt. Schreibe zusätzlich eine Methode stopThread(
String name)
, die den Thread beendet.
Mit dieser Klasse ist es einfach möglich, Thread mit Namen anzusprechen. Man benötigt
dann keine Referenz mehr.
TimerLabel
, die von
java.awt.Label
abgeleitet ist. Setze ein Objekt dieser Klasse auf ein
java.awt.Frame
zur Anzeige. TimerLabel
soll jetzt
java.lang.Runnable
implementieren. In der run()
-Methode soll in einer Endlosschleife
immer wieder mit der Label-Funktion setText()
die aktuelle Tageszeit
gesetzt werden. Starte den Thread aus dem Hauptprogramm, wo auch TimerLabel
erzeugt wird. TimerLabel
auch selbst übernehmen.
Schreibe einen Standard-Konstruktor, der den Thread selbst startet. In dem Konstruktor
von Thread()
müssen wir nur this
übergeben.Klasse
Uhrzeit, der Frame
Klasse
TimeLabel
Implementiere einen Thread, der durch die Division mit Null eine Exception wirft.
Fange den Fehlerfall dieses speziellen Threads durch einen
UncaughtExceptionHandler
ab.
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?
Es gibt die Objektvariable Point p = new Point()
und gleichzeitig
zwei Threads. Der eine führt p.setLocation(1, 2)
aus, der andere
p.setLocation(2, 1)
. Welches Problem könnte durch die Threads entstehen,
wenn sie parallel auf die Methoden zugreifen?
Löse das Problem durch die Möglichkeiten der Java-API.