diff --git a/08-termin.md b/08-termin.md new file mode 100644 index 0000000..d07d7f2 --- /dev/null +++ b/08-termin.md @@ -0,0 +1,39 @@ + + +# Termin 8 + +--- + +# Fragen + +--- + +# Links +[https://git.haw-hamburg.de/pm2-tutorium](https://git.haw-hamburg.de/pm2-tutorium) +- Aufgaben +- Tutoriumsfolien + * In Präsentationsansicht: [https://wi-pm2-tut.informatik.haw-hamburg.de](https://wi-pm2-tut.informatik.haw-hamburg.de/) + +--- + +# Plan für heute + +Level 7 Themen: + +- Objektorientierter Entwurf +- **Nebenläufikeit 1** + +--- + +# Plan + +* Heute ist der letzte Termin. +* 1.7. findet nicht statt, aber es gibt eine Aufzeichnung. +* Prüfungsvorberreitung wird es im Anschluss geben, gibt es aber auch in aufgezeichneter Form. +* Fragen gerne auf Teams stellen. Am Montag den 5.7. um 11 Uhr gibt es noch eine Fragestunde, die auch aufgezeichnet wird. diff --git a/nebenlaeufigkeit.md b/nebenlaeufigkeit.md new file mode 100644 index 0000000..fe308fa --- /dev/null +++ b/nebenlaeufigkeit.md @@ -0,0 +1,155 @@ + + +# Nebenläufigkeit + +--- + +# Grundlagen + +Computer führen mehr als eine Aufgabe gleichzeitig aus. Auch innerhalb eine Programms können wir quasi gleichzeitige Ausführung von Programmcode programmieren. Diese Art der Programmierung bezeichnen wir als nebenläufig. + +Es gibt zwei verschiedene Ausführungseinheiten: + +* **Prozesse**: Besitzen eigene Laufzeitresourcen, am wichtigsten auch einen eigenen Speicherbereich +* **Threads**: Sind leichtgewichtige Prozesse. Threads existieren in einem Prozess und teilen sich Laufzeitresourcen mit ihm, wie den Speicherbereich und geöffnete Dateien. + +Die meisten JVMs laufen in einem einzigen Prozess. + +--- + +# System Threads + +Zwei Threads haben wir bereits benutzt. Den main-Thread und den GUI-Thread von JavaFX (`application thread`). + +--- + +# Deklaration + +In Java gibt es zwei Möglichkeiten einen neuen Thread zu erzeugen. Entweder man erbt von der Klasse `Thread` oder man implementiert das Interface `Runnable`. + +--- + +# Von `Thread` erben + +```java +class HelloThread extends Thread { + public void run() { + System.out.println("Hallo aus einem Thread"); + } +} +``` +```java +Thread thread = new HelloThread(); +thread.start(); +``` +- Simpel: Einfache Implementation +- Unflexibel: Nebenläufige Klasse muss immer eine Subklasse von `Thread` sein + +--- + +# `Runnable` implementieren +```java +class HelloThread implements Runnable { + public void run() { + System.out.println("Hallo aus einem Thread"); + } +} +``` +```java +Thread thread = new Thread(new HelloThread()); +thread.start(); +``` + +- Kompliziert: Etwas schwieriger zu starten +- Flexibel: Die nebenläufige Klasse kann beliebige Superklassen haben + +--- + +# Einen Thread pausieren + +Mithilfe der Methode `Thread.sleep(long milliseconds) throws InterruptedException` kann ein Thread in seiner Ausführung pausiert werden. + +```java +class HelloThread implements Runnable { + public void run() { + System.out.println("Hallo aus einem Thread"); + + try { + Thread.sleep(1000); + } catch (InterruptedException e ) { + e.printStacktrace(); + } + + System.out.println("Hallo 1 Sekunde später") + } +} +``` +--- + +# Einen Thread unterbrechen + +Ein Thread `thread1` kann von einem anderen Thread `thread2` mithilfe der Methode `thread1.interrupt()` unterbrochen werden. Wird ein Thread unterbrochen wird der `Interrupted-State` gesetzt. Der kann mithilfe der Methode `Thread.interrupted()` abgefragt werden. Ist der Thread aktuell pausiert wird die `InterruptedException` der Methode `sleep` geworfen. + +In beiden Fällen kann der Thread selbst entscheiden ob er abbrechen will. + +```java +Thread thread = new Thread(new LongRunningThread()); +thread.start(); +thread.interrupt(); +``` + +--- + +# Auf einen Thread warten + +Wenn wir aus einem Thread auf die Beendung eines anderen Threads warten wollen, können wir dafür die Methode `join()` nutzen. + + +```java +Thread thread = new Thread(new LongRunningThread()); +thread.start(); +System.out.println("Jetzt läuft der Thread"); +thread.join(); +System.out.println("Jetzt ist der Thread fertig"); +``` +--- + +# Lost update problem + +```java +class Counter { + private int c = 0; + + public void decrement() { + c--; + } +} + +``` +Intern wird `decrement()` auf jeweils drei Operationen abgebildet: + +1) Aktuellen Wert von `c` holen +2) Den ermittelten Wert um 1 dekrementieren +3) Das Ergebnis in `c` speichern + +--- + +# Lost update problem + +Thread `A` und Thread `B` wollen beide den Zähler dekrementieren. Das kann dazu führen das folgendes passiert: + +Ausgangslage: Das Feld `c` hat den Wert `5`. + +1) Thread `A`: Aktuellen Wert von `c` holen +2) Thread `B`: Aktuellen Wert von `c` holen +3) Thread `A`: Den ermittelten Wert um 1 dekrementieren. Ergebnis ist `4`. +4) Thread `B`: Den ermittelten Wert um 1 dekrementieren. Ergebnis ist `4`. +5) Thread `A`: Den ermittelten Wert in `c` abspeichern. `c` ist jetzt `4`. +6) Thread `B`: Den ermittelten Wert in `c` abspeichern. `c` ist jetzt `4`. +