In den meisten Fällen wird auf einem mono-Prozessorsystem gearbeitet, selbst wenn es sich um ein mehr-Prozessorsystem handelt, können die Anzahl verlangter Threads die Anzahl installierter Prozessoren übersteigen. In diesem Fall wird das parallele Verarbeiten nur simuliert.
D.h. ein Thread läuft nur dann wenn gerade die Kapazität dazu frei ist, d.h. ein anderer Thread gerade Zyklen-freigibt (mit yield();), anhält oder sich auflöst; auf Betriebsysteme die nach dem sogenannten Time-slicing Verfahren arbeiten, sit eine weitere Möglichkeit, daß ein Thread seine maximale Anzahl Zyklen aufgebraucht hat. Stehen mehrere threads zur bearbeitung aus wird der mit der höchsten Priorität ausgewählt. Muß zwischen gleich-prioritären Threads gewählt werden, werden sie zyklisch ausgewählt.
Es ist möglich (mit setPriority) die Priorität eines Threads zu verändern, sonst behält dieser die die er von seinem Elter bekommen hat.
public class SimpleThread extends Thread { public SimpleThread(String str) { super(str); } public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getName()); try { sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) {} }// for (int i = 0; i < 10; i++) System.out.println("DONE! " + getName()); }// public void run() }// public class SimpleThread extends Thread
Diese Klasse erbt von Thread, das auffälligste ist, daß die Methode run entsprechend ausgebaut werden muß, dies ist die Methode, welche aufgerufen wird wenn der Thread gestartet wird. Ist die Ausführung in run() zuende, stirbt auch der Thread. In diesem Fall wird der Thread 10 mal aufweckbar sein, danach wird er zu existieren aufgehört haben.
Der Inhalt der run-Methode ist entsprechend: eine Schleife mit 10 Durchläufen, eine Ausgabe, x mal 1s warten und weiterschleifen.
Um diese Klasse zu testen, kann folgendes Programm benutzt werden:
public class TwoThreadsTest { public static void main (String[] args) { new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); }// public static void main (String[] args) }// public class TwoThreadsTestDamit bekäme man beispielsweise folgende Ausgabe:
0 Jamaica 0 Fiji 1 Fiji 1 Jamaica 2 Fiji 2 Jamaica 3 Fiji 3 Jamaica 4 Jamaica 4 Fiji 5 Jamaica 5 Fiji 6 Jamaica 6 Fiji 7 Fiji 8 Fiji 9 Fiji 7 Jamaica 8 Jamaica 9 Jamaica DONE! Fiji DONE! Jamaica
Hier wird die Methode run implementiert, und die Konformität dieser Klasse zum Typ Runnable erzwungen indem das Interface Runnable implementiert wurde.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"); clockThread.start(); } } public void run() { Thread myThread = Thread.currentThread(); while (clockThread == myThread) { repaint(); try { Thread.sleep(1000); } catch (InterruptedException e){ // the VM doesn't want us to sleep anymore, // so get back to work } } } public void paint(Graphics g) { // get the time and convert it to a date Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); // format it and display it DateFormat dateFormatter = DateFormat.getTimeInstance(); g.drawString(dateFormatter.format(date), 5, 10); } // overrides Applet's stop method, not Thread's public void stop() { clockThread = null; } }
Damit ist es möglich dieses Objekt einem Thread zu übergeben, dessen einzige Aktivität das Ausführen der Run-Methode unseres Objektes ist.
isAlive()
-Methode abzufragen, kommt false
zurück ist der Thread entweder ein neuer Thread oder schon tot.
Folgendes Bild illustriert diesen Zyklus:
IllegalThreadStateException
-Fehler.
start()
gestartet, diese ruft die Methode
run()
des Threads auf. Jetzt erst werden die Systemressourcen
angelegt und die Ausführung beginnt.
Entsprechend kann ein Thread nur dann in den laufenden Zustand gebracht werden, wenn der inverse Weg beschritten wird. D.h.
Nun ist es aber in der Regel der Fall, daß ein Thread von den Daten, die ein anderer produzieren kann abhängig. D.h. die Threads müssen sich untereinander "absprechen" um keine Miß-lesungen zu machen.
Dies ist ein komplexes Thema, welches außer Software-Mechanismen wie
Object-locking (dank des synchronized Modificators) oder Semaphoren (Jeder
Thread ist sein eignener Semaphor, das Auslösen erfolgt durch die
wait
-Methode auch viel Designphilosophie einschließt um Probleme
wie Dead-Locks (alle Threads manövrieren sich in einen Zustand, bei dem alle
auf alle warten und nichts mehr passiert)
Der Timer wird mit start()
gestartet, und mit
stop()
gestoppt.
Document mit wml erzeugt von Bruno Böttcher unter Benutzung von öffentlichen Dokumenten.