Learning By Doing Multithreading (Nebenläufigkeit) • Alte Idee der Parallelverarbeitung statt rein sequentieller Prozesse • Parallelverarbeitung kann auf einem Einprozessorsystem simuliert werden und trotzdem grosse Vorteile aufweisen. Die Prozesse laufen dann quasi-parallel • Ein Prozess-Scheduler sorgt für die "Umschaltung" (Context switch) der Prozesse • Hauptschwierigkeit: Konfliktfreie Verwaltung gemeinsamer Ressourcen Scheduler Prozess 1 Prozess 2 Gemeinsame Ressourcen Learning By Doing Threads, Deadlock • Statt Prozesse können auch Programmteile eines einzelnen Programms quasi-parallel laufen. Diese werden Threads (Fäden) genannt • Multithread-Programme sind aber bezüglich Programmierlogik (und für den Entwickler der Programmiersprache) anspruchsvoll, da die Threads üblicherweise zusammenarbeiten müssen • Grundregeln: • Man entkopple die Threads so weit wie möglich • Man achte auf alle Seiteneffekte (so lokal wie möglich, so wenig global wie möglich) • Muss ein Thread auf die Ergebnisse eines anderen warten, so besteht immer die Gefahr eines Deadlocks! Ich warte auf das Schreibzeug... G äs te Ich warte auf das Buch... Ha,ha... die warten in alle Ewigkeit s. Buch S. 467ff Learning By Doing Multithreading-Konzept in Java • Klasse Wanderweg schreiben, die das Interface Runnable, d.h. die Methode run() implementiert • Objekt dieser Klasse instanzieren, liefert Referenz ww1 • Objekt der Klasse Thread instanzieren und dabei die Objektreferenz ww1 übergeben • start()-Methode des Threads aufrufen Der Scheduler erzeugt einen neuen Thread und ruft run() auf. Der Thread "stirbt", sobald run() zu Ende läuft. // WbzEx18.java import ch.aplu.turtle.*; class Wanderweg Wanderweg implements implements extends Thread Runnable class Runnable { private Turtle t = new Turtle(); private double angle; public Wanderweg(double angle) { this.angle = angle; } public void void run() run() public {{ while (true) (true) while {{ t.forward(100); t.forward(100); t.left(angle); t.left(angle); }} }} } public class WbzEx18 { public WbzEx18() { Wanderweg ww1 = new Wanderweg(70); Thread thread1 = new Thread(ww1); thread1.start(); Wanderweg ww2 = new Wanderweg(110); Thread thread2 = new Thread(ww2); thread2.start(); } public static void main(String[] args) { new WbzEx18(); } } Alternative: Wanderweg von Thread ableiten Learning By Doing Thread beenden • Um einen Thread zu beenden, lässt man die run()-Methode zu Ende laufen • Man verwendet dazu eine boolesches Flag isRunning • WanderTurtle ist eine Innere Klasse, damit sie und WbzEx19 Zugriff auf isRunning haben • isRunning sollte man volatile deklarieren, da zwei verschiedene Threads darauf zugreifen // WbzEx19.java volatileboolean privateisRunning boolean isRunning private = true; = true; import ch.aplu.turtle.*; public WbzEx19() { new Thread(new WanderTurtle(70)).start(); try { Thread.currentThread().sleep(5000); } catch (InterruptedException ex) {} isRunning = false; } public class WbzEx19 { class WanderTurtle extends Turtle implements Runnable { private double angle; public WanderTurtle(double angle) { this.angle = angle; } public void run() { label("Habe Volldampf"); while (isRunning) { forward(100); left(angle); } label("Bin müde"); } } public static void main(String[] args) { new WbzEx19(); } }