Add termin8
This commit is contained in:
parent
e16988cfcd
commit
f6d3032e74
|
@ -0,0 +1,39 @@
|
||||||
|
<!--
|
||||||
|
title: Termin 8
|
||||||
|
description: Folien für den ersten Termin in Programmieren 2
|
||||||
|
url: https://git.haw-hamburg.de/pm2-tutorium/slides
|
||||||
|
header: Programmieren 2 **Tutorium**
|
||||||
|
footer: Henri Burau
|
||||||
|
-->
|
||||||
|
|
||||||
|
# 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.
|
|
@ -0,0 +1,155 @@
|
||||||
|
<!--
|
||||||
|
title: Nebenläufigkeit
|
||||||
|
description: Folien für Nebenläufigkeit in Programmieren 2
|
||||||
|
url: https://git.haw-hamburg.de/pm2-tutorium/slides
|
||||||
|
header: Programmieren 2 **Tutorium**
|
||||||
|
footer: Henri Burau
|
||||||
|
-->
|
||||||
|
|
||||||
|
# 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`.
|
||||||
|
|
Loading…
Reference in New Issue