diff --git a/src/pp.10.00-Exchanger/README.md b/src/pp.10.00-Exchanger/README.md
new file mode 100644
index 0000000..b37d990
--- /dev/null
+++ b/src/pp.10.00-Exchanger/README.md
@@ -0,0 +1,9 @@
+# Laboraufgabe "naive ``Exchanger``-Implementierung"
+
+Dies hier ist eine naive (und teilweise) Implementierung eines [Exchangers](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Exchanger.html).
+
+Die reale Implementierung ist weitaus komplexer: https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/concurrent/Exchanger.java
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/10-csp.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/i10-csp.html)
diff --git a/src/pp.10.00-Exchanger/pom.xml b/src/pp.10.00-Exchanger/pom.xml
new file mode 100644
index 0000000..222add8
--- /dev/null
+++ b/src/pp.10.00-Exchanger/pom.xml
@@ -0,0 +1,69 @@
+
+ 4.0.0
+ pp
+ pp.10.00-Exchanger
+ 0.0.1-SNAPSHOT
+
+ 10
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile test
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pp.10.00-Exchanger/src/main/java/pp/SimpleExchanger.java b/src/pp.10.00-Exchanger/src/main/java/pp/SimpleExchanger.java
new file mode 100644
index 0000000..c2a33b4
--- /dev/null
+++ b/src/pp.10.00-Exchanger/src/main/java/pp/SimpleExchanger.java
@@ -0,0 +1,30 @@
+package pp;
+
+import net.jcip.annotations.ThreadSafe;
+
+@ThreadSafe
+public class SimpleExchanger {
+ private T left, right;
+ private Object monitor = new Object();
+
+ public T exchange(T data) throws InterruptedException {
+ synchronized (this.monitor) {
+ if (this.left == null && this.right == null) {
+ this.left = data;
+ while (this.right == null) {
+ this.monitor.wait();
+ }
+ return this.right;
+ } else {
+ this.right = data;
+ this.monitor.notify();
+ try {
+ return this.left;
+ } finally {
+ this.left = null;
+ this.right = null;
+ }
+ }
+ }
+ }
+}
diff --git a/src/pp.10.00-Exchanger/src/test/java/pp/ExchangerTest.java b/src/pp.10.00-Exchanger/src/test/java/pp/ExchangerTest.java
new file mode 100644
index 0000000..67c5c83
--- /dev/null
+++ b/src/pp.10.00-Exchanger/src/test/java/pp/ExchangerTest.java
@@ -0,0 +1,66 @@
+package pp;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class ExchangerTest {
+ final private SimpleExchanger e = new SimpleExchanger<>();
+
+ @Test
+ void test1() {
+ new Thread(() -> {
+ try {
+ assertEquals(Integer.valueOf(2), e.exchange(Integer.valueOf(1)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ new Thread(() -> {
+ try {
+ assertEquals(Integer.valueOf(1), e.exchange(Integer.valueOf(2)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ }
+
+ @Test
+ void test2() {
+ new Thread(() -> {
+ try {
+ Thread.sleep(1000);
+ assertEquals(Integer.valueOf(3), e.exchange(Integer.valueOf(4)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ new Thread(() -> {
+ try {
+ assertEquals(Integer.valueOf(4), e.exchange(Integer.valueOf(3)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ }
+
+ @Test
+ void test3() {
+ new Thread(() -> {
+ try {
+ assertEquals(Integer.valueOf(5), e.exchange(Integer.valueOf(6)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ new Thread(() -> {
+ try {
+ Thread.sleep(1000);
+ assertEquals(Integer.valueOf(6), e.exchange(Integer.valueOf(5)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }).start();
+ }
+
+}
diff --git a/src/pp.10.01.Rendezvous/README.md b/src/pp.10.01.Rendezvous/README.md
new file mode 100644
index 0000000..d7dbda6
--- /dev/null
+++ b/src/pp.10.01.Rendezvous/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "CSP mit Java-Mitteln"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-01-Rendezvous.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-Solutions.html#laboraufgabe-csp-mit-java-mitteln)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/10-csp.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/i10-csp.html)
diff --git a/src/pp.10.01.Rendezvous/pom.xml b/src/pp.10.01.Rendezvous/pom.xml
new file mode 100644
index 0000000..4b31f5f
--- /dev/null
+++ b/src/pp.10.01.Rendezvous/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+ pp
+ pp.10.01.Rendezvous
+ 1.0-SNAPSHOT
+ jar
+
+
+ io.dama.ffi.rendezvous.Sum
+ 10
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pp.10.01.Rendezvous/src/main/java/pp/Sum.java b/src/pp.10.01.Rendezvous/src/main/java/pp/Sum.java
new file mode 100644
index 0000000..a600b12
--- /dev/null
+++ b/src/pp.10.01.Rendezvous/src/main/java/pp/Sum.java
@@ -0,0 +1,27 @@
+package pp;
+
+/*-
+
+package main
+import "fmt"
+func tasker (o, r chan int, d chan bool) {
+ o <- 1; o <- 2
+ fmt.Println (<-r); d <- true
+}
+func add (o, r chan int) {
+ r <- ((<-o) + (<-o))
+}
+func main () {
+ operand, result := make(chan int), make(chan int)
+ done:= make(chan bool)
+ go tasker (operand, result, done)
+ go add (operand, result)
+ <-done
+}
+
+ */
+
+public class Sum {
+ public static void main(String... args) {
+ }
+}
diff --git a/src/pp.10.01.Rendezvous_solution/README.md b/src/pp.10.01.Rendezvous_solution/README.md
new file mode 100644
index 0000000..d7dbda6
--- /dev/null
+++ b/src/pp.10.01.Rendezvous_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "CSP mit Java-Mitteln"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-01-Rendezvous.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-Solutions.html#laboraufgabe-csp-mit-java-mitteln)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/10-csp.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/i10-csp.html)
diff --git a/src/pp.10.01.Rendezvous_solution/pom.xml b/src/pp.10.01.Rendezvous_solution/pom.xml
new file mode 100644
index 0000000..44adadb
--- /dev/null
+++ b/src/pp.10.01.Rendezvous_solution/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+ pp
+ pp.10.01.Rendezvous_solution
+ 1.0-SNAPSHOT
+ jar
+
+
+ pp.Sum
+ 10
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile exec:java
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pp.10.01.Rendezvous_solution/src/main/java/pp/Sum.java b/src/pp.10.01.Rendezvous_solution/src/main/java/pp/Sum.java
new file mode 100644
index 0000000..fba5c10
--- /dev/null
+++ b/src/pp.10.01.Rendezvous_solution/src/main/java/pp/Sum.java
@@ -0,0 +1,56 @@
+package pp;
+
+/*-
+
+package main
+import "fmt"
+func tasker (o, r chan int, d chan bool) {
+ o <- 1; o <- 2
+ fmt.Println (<-r); d <- true
+}
+func add (o, r chan int) {
+ r <- ((<-o) + (<-o))
+}
+func main () {
+ operand, result := make(chan int), make(chan int)
+ done:= make(chan bool)
+ go tasker (operand, result, done)
+ go add (operand, result)
+ <-done
+}
+
+ */
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class Sum {
+ static void tasker(int x, int y, BlockingQueue o,
+ BlockingQueue r, BlockingQueue d) {
+ o.offer(x);
+ o.offer(y);
+ try {
+ System.out.println(r.take());
+ d.put(true);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ static void add(BlockingQueue o, BlockingQueue r) {
+ try {
+ r.put(o.take() + o.take());
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ public static void main(String... args) throws InterruptedException {
+ var operand = new LinkedBlockingQueue();
+ var result = new LinkedBlockingQueue();
+ var done = new LinkedBlockingQueue();
+ (new Thread(() -> tasker(1, 2, operand, result, done))).start();
+ (new Thread(() -> add(operand, result))).start();
+ done.take();
+ }
+}
diff --git a/src/pp.10.02.Logger/README.md b/src/pp.10.02.Logger/README.md
new file mode 100644
index 0000000..9808e16
--- /dev/null
+++ b/src/pp.10.02.Logger/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Logging in Multi-Threadumgebungen"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-02-Logger.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-Solutions.html#laboraufgabe-logging-in-multi-threadumgebungen)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/10-csp.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/i10-csp.html)
diff --git a/src/pp.10.02.Logger/pom.xml b/src/pp.10.02.Logger/pom.xml
new file mode 100644
index 0000000..f2de1c5
--- /dev/null
+++ b/src/pp.10.02.Logger/pom.xml
@@ -0,0 +1,71 @@
+
+ 4.0.0
+ pp
+ pp.10.02.Logger
+ 1.0-SNAPSHOT
+ jar
+
+
+ 19
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pp.10.02.Logger/src/main/java/pp/Logging.java b/src/pp.10.02.Logger/src/main/java/pp/Logging.java
new file mode 100644
index 0000000..2859326
--- /dev/null
+++ b/src/pp.10.02.Logger/src/main/java/pp/Logging.java
@@ -0,0 +1,20 @@
+package pp;
+
+import java.io.PrintStream;
+
+public interface Logging {
+ public enum Severity {
+ Debug, Info, Notice, Warning, Error, Critical, Alert, Emergency;
+ }
+
+ void log(Severity level, String msg);
+
+ void flush();
+
+ void setPrintStream(PrintStream out);
+
+ void setSeverityLevel(Severity level);
+
+ Severity getSeverityLevel();
+
+}
diff --git a/src/pp.10.02.Logger/src/main/java/pp/QueuedLogger.java b/src/pp.10.02.Logger/src/main/java/pp/QueuedLogger.java
new file mode 100644
index 0000000..eee283c
--- /dev/null
+++ b/src/pp.10.02.Logger/src/main/java/pp/QueuedLogger.java
@@ -0,0 +1,67 @@
+package pp;
+
+import java.io.PrintStream;
+
+final class QueuedLogger extends Thread implements Logging {
+
+ private final Logging logger;
+
+ // ... TODO: BlockingQueues deklarieren ...
+
+ public QueuedLogger() {
+ logger = null; // ... TODO: initialisieren ...
+ // ... TODO: BlockingQueues initialisieren ...
+ setDaemon(true);
+ setPriority(Thread.MIN_PRIORITY);
+ start(); // hier kein Problem, da Klasse final (s. pp.01.01-Inheritance)
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ // ... TODO: BlockingQueues auswerten und loggen ...
+ }
+ }
+
+ @Override
+ public void log(Severity level, String msg) {
+ switch (level) {
+ case Debug:
+ // ... TODO: Blocking Queue befüllen ...
+ case Info:
+ // ... TODO: Blocking Queue befüllen ...
+ case Notice:
+ // ... TODO: Blocking Queue befüllen ...
+ case Warning:
+ // ... TODO: Blocking Queue befüllen ...
+ case Error:
+ // ... TODO: Blocking Queue befüllen ...
+ case Critical:
+ // ... TODO: Blocking Queue befüllen ...
+ case Alert:
+ // ... TODO: Blocking Queue befüllen ...
+ case Emergency:
+ // ... TODO: Blocking Queue befüllen ...
+ }
+ }
+
+ @Override
+ public void flush() {
+ logger.flush();
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ logger.setSeverityLevel(level);
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return logger.getSeverityLevel();
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ logger.setPrintStream(out);
+ }
+}
diff --git a/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerSafe.java b/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerSafe.java
new file mode 100644
index 0000000..968c0c9
--- /dev/null
+++ b/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerSafe.java
@@ -0,0 +1,48 @@
+package pp;
+
+import java.io.PrintStream;
+
+public class SimpleLoggerSafe implements Logging, AutoCloseable {
+ public SimpleLoggerSafe() {
+ // ... TODO ...
+ }
+
+ public SimpleLoggerSafe(Severity level) {
+ // ... TODO ...
+ }
+
+ public SimpleLoggerSafe(Severity level, PrintStream out) {
+ // ... TODO ...
+ }
+
+ @Override
+ public void close() throws Exception {
+ // ... TODO ...
+ }
+
+ @Override
+ public void log(Severity level, String msg) {
+ // ... TODO ...
+ }
+
+ @Override
+ public void flush() {
+ // ... TODO ...
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ // ... TODO ...
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ // ... TODO ...
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ // ... TODO ...
+ return null;
+ }
+}
diff --git a/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerUnsafe.java b/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerUnsafe.java
new file mode 100644
index 0000000..4b0b7a5
--- /dev/null
+++ b/src/pp.10.02.Logger/src/main/java/pp/SimpleLoggerUnsafe.java
@@ -0,0 +1,65 @@
+package pp;
+
+import java.io.PrintStream;
+
+public class SimpleLoggerUnsafe implements Logging, AutoCloseable {
+ private static final int CAPACITY = 1024;
+ private final StringBuilder log = new StringBuilder(CAPACITY);
+ private Severity level;
+ private PrintStream out;
+
+ public SimpleLoggerUnsafe() {
+ setSeverityLevel(Logging.Severity.Warning);
+ setPrintStream(System.err);
+ }
+
+ public SimpleLoggerUnsafe(Severity level) {
+ this();
+ setSeverityLevel(level);
+ }
+
+ public SimpleLoggerUnsafe(Severity level, PrintStream out) {
+ this(level);
+ setPrintStream(out);
+ }
+
+ @Override
+ public void log(Severity level, String msg) {
+ if (this.level.ordinal() <= level.ordinal()) {
+ if ((this.log.length() + msg.length() //
+ + System.lineSeparator().length()) >= log.capacity()) {
+ flush();
+ }
+ this.log.append(msg).append(System.lineSeparator());
+ }
+ }
+
+ @Override
+ public void flush() {
+ if (this.log.length() > 0) {
+ this.out.print(this.log);
+ this.out.flush();
+ this.log.setLength(0);
+ }
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ this.level = level;
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ this.out = out;
+ }
+
+ @Override
+ public void close() throws Exception {
+ flush();
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return this.level;
+ }
+}
diff --git a/src/pp.10.02.Logger/src/main/java/pp/ThreadLocalLogger.java b/src/pp.10.02.Logger/src/main/java/pp/ThreadLocalLogger.java
new file mode 100644
index 0000000..d298d51
--- /dev/null
+++ b/src/pp.10.02.Logger/src/main/java/pp/ThreadLocalLogger.java
@@ -0,0 +1,37 @@
+package pp;
+
+import java.io.PrintStream;
+
+public class ThreadLocalLogger implements Logging {
+
+ private ThreadLocal logger = ThreadLocal.withInitial(() -> {
+ // hier programmieren und ein ThreadLocal statt null
+ // zurückgeben
+ return null;
+ });
+
+ @Override
+ public void log(Severity level, String msg) {
+ logger.get().log(level, msg);
+ }
+
+ @Override
+ public void flush() {
+ logger.get().flush();
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ logger.get().setSeverityLevel(level);
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return logger.get().getSeverityLevel();
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ logger.get().setPrintStream(out);
+ }
+}
\ No newline at end of file
diff --git a/src/pp.10.02.Logger_solution/README.md b/src/pp.10.02.Logger_solution/README.md
new file mode 100644
index 0000000..9808e16
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/README.md
@@ -0,0 +1,7 @@
+# Laboraufgabe "Logging in Multi-Threadumgebungen"
+- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-02-Logger.html)
+- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/10-Solutions.html#laboraufgabe-logging-in-multi-threadumgebungen)
+
+# Materialien
+- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/10-csp.html)
+- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/i10-csp.html)
diff --git a/src/pp.10.02.Logger_solution/pom.xml b/src/pp.10.02.Logger_solution/pom.xml
new file mode 100644
index 0000000..f509b40
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/pom.xml
@@ -0,0 +1,71 @@
+
+ 4.0.0
+ pp
+ pp.10.02.Logger_solution
+ 1.0-SNAPSHOT
+ jar
+
+
+ 19
+ edge-SNAPSHOT
+ UTF-8
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.10.0
+ test
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+ provided
+
+
+
+ clean compile
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.9.0
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+ private
+ en_US
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pp.10.02.Logger_solution/src/main/java/pp/Logging.java b/src/pp.10.02.Logger_solution/src/main/java/pp/Logging.java
new file mode 100644
index 0000000..2859326
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/src/main/java/pp/Logging.java
@@ -0,0 +1,20 @@
+package pp;
+
+import java.io.PrintStream;
+
+public interface Logging {
+ public enum Severity {
+ Debug, Info, Notice, Warning, Error, Critical, Alert, Emergency;
+ }
+
+ void log(Severity level, String msg);
+
+ void flush();
+
+ void setPrintStream(PrintStream out);
+
+ void setSeverityLevel(Severity level);
+
+ Severity getSeverityLevel();
+
+}
diff --git a/src/pp.10.02.Logger_solution/src/main/java/pp/QueuedLogger.java b/src/pp.10.02.Logger_solution/src/main/java/pp/QueuedLogger.java
new file mode 100644
index 0000000..c7886d4
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/src/main/java/pp/QueuedLogger.java
@@ -0,0 +1,104 @@
+package pp;
+
+import java.io.PrintStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+final class QueuedLogger extends Thread implements Logging {
+ private final Logging logger;
+ private final BlockingQueue queueDebug;
+ private final BlockingQueue queueInfo;
+ private final BlockingQueue queueNotice;
+ private final BlockingQueue queueWarning;
+ private final BlockingQueue queueError;
+ private final BlockingQueue queueCritical;
+ private final BlockingQueue queueAlert;
+ private final BlockingQueue queueEmergency;
+
+ public QueuedLogger() {
+ logger = new SimpleLoggerUnsafe();
+ queueDebug = new LinkedBlockingQueue<>();
+ queueInfo = new LinkedBlockingQueue<>();
+ queueNotice = new LinkedBlockingQueue<>();
+ queueWarning = new LinkedBlockingQueue<>();
+ queueError = new LinkedBlockingQueue<>();
+ queueCritical = new LinkedBlockingQueue<>();
+ queueAlert = new LinkedBlockingQueue<>();
+ queueEmergency = new LinkedBlockingQueue<>();
+ setDaemon(true);
+ setPriority(Thread.MIN_PRIORITY);
+ start(); // hier kein Problem, da Klasse final (s. pp.01.01-Inheritance)
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ var msg = "";
+ if ((msg = this.queueEmergency.poll()) != null) {
+ logger.log(Severity.Emergency, msg);
+ } else if ((msg = this.queueAlert.poll()) != null) {
+ logger.log(Severity.Alert, msg);
+ } else if ((msg = this.queueCritical.poll()) != null) {
+ logger.log(Severity.Critical, msg);
+ } else if ((msg = this.queueError.poll()) != null) {
+ logger.log(Severity.Error, msg);
+ } else if ((msg = this.queueWarning.poll()) != null) {
+ logger.log(Severity.Warning, msg);
+ } else if ((msg = this.queueNotice.poll()) != null) {
+ logger.log(Severity.Notice, msg);
+ } else if ((msg = this.queueInfo.poll()) != null) {
+ logger.log(Severity.Info, msg);
+ } else if ((msg = this.queueDebug.poll()) != null) {
+ logger.log(Severity.Debug, msg);
+ }
+ }
+ }
+
+ @Override
+ public void log(Severity level, String msg) {
+ if (logger.getSeverityLevel().ordinal() <= level.ordinal()) {
+ var success = false;
+ while (!success) { // falls die jeweilige Queue schon voll ist
+ // (success == false) nochmal probieren
+ switch (level) {
+ case Debug:
+ success = this.queueDebug.offer(msg);
+ case Info:
+ success = this.queueInfo.offer(msg);
+ case Notice:
+ success = this.queueNotice.offer(msg);
+ case Warning:
+ success = this.queueWarning.offer(msg);
+ case Error:
+ success = this.queueError.offer(msg);
+ case Critical:
+ success = this.queueCritical.offer(msg);
+ case Alert:
+ success = this.queueAlert.offer(msg);
+ case Emergency:
+ success = this.queueEmergency.offer(msg);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void flush() {
+ logger.flush();
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ logger.setSeverityLevel(level);
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return logger.getSeverityLevel();
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ logger.setPrintStream(out);
+ }
+}
diff --git a/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerSafe.java b/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerSafe.java
new file mode 100644
index 0000000..5b4769a
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerSafe.java
@@ -0,0 +1,49 @@
+package pp;
+
+import java.io.PrintStream;
+
+public class SimpleLoggerSafe extends SimpleLoggerUnsafe
+ implements Logging, AutoCloseable {
+
+ public SimpleLoggerSafe() {
+ super();
+ }
+
+ public SimpleLoggerSafe(Severity level) {
+ super(level);
+ }
+
+ public SimpleLoggerSafe(Severity level, PrintStream out) {
+ super(level, out);
+ }
+
+ @Override
+ public synchronized void log(Severity level, String msg) {
+ super.log(level, msg);
+ }
+
+ @Override
+ public synchronized void flush() {
+ super.flush();
+ }
+
+ @Override
+ public synchronized void setSeverityLevel(Severity level) {
+ super.setSeverityLevel(level);
+ }
+
+ @Override
+ public synchronized void setPrintStream(PrintStream out) {
+ super.setPrintStream(out);
+ }
+
+ @Override
+ public synchronized void close() throws Exception {
+ super.close();
+ }
+
+ @Override
+ public synchronized Severity getSeverityLevel() {
+ return super.getSeverityLevel();
+ }
+}
diff --git a/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerUnsafe.java b/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerUnsafe.java
new file mode 100644
index 0000000..4b0b7a5
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/src/main/java/pp/SimpleLoggerUnsafe.java
@@ -0,0 +1,65 @@
+package pp;
+
+import java.io.PrintStream;
+
+public class SimpleLoggerUnsafe implements Logging, AutoCloseable {
+ private static final int CAPACITY = 1024;
+ private final StringBuilder log = new StringBuilder(CAPACITY);
+ private Severity level;
+ private PrintStream out;
+
+ public SimpleLoggerUnsafe() {
+ setSeverityLevel(Logging.Severity.Warning);
+ setPrintStream(System.err);
+ }
+
+ public SimpleLoggerUnsafe(Severity level) {
+ this();
+ setSeverityLevel(level);
+ }
+
+ public SimpleLoggerUnsafe(Severity level, PrintStream out) {
+ this(level);
+ setPrintStream(out);
+ }
+
+ @Override
+ public void log(Severity level, String msg) {
+ if (this.level.ordinal() <= level.ordinal()) {
+ if ((this.log.length() + msg.length() //
+ + System.lineSeparator().length()) >= log.capacity()) {
+ flush();
+ }
+ this.log.append(msg).append(System.lineSeparator());
+ }
+ }
+
+ @Override
+ public void flush() {
+ if (this.log.length() > 0) {
+ this.out.print(this.log);
+ this.out.flush();
+ this.log.setLength(0);
+ }
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ this.level = level;
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ this.out = out;
+ }
+
+ @Override
+ public void close() throws Exception {
+ flush();
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return this.level;
+ }
+}
diff --git a/src/pp.10.02.Logger_solution/src/main/java/pp/ThreadLocalLogger.java b/src/pp.10.02.Logger_solution/src/main/java/pp/ThreadLocalLogger.java
new file mode 100644
index 0000000..de21bb4
--- /dev/null
+++ b/src/pp.10.02.Logger_solution/src/main/java/pp/ThreadLocalLogger.java
@@ -0,0 +1,48 @@
+package pp;
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+
+import javax.naming.OperationNotSupportedException;
+
+public class ThreadLocalLogger implements Logging {
+
+ private ThreadLocal logger = ThreadLocal.withInitial(() -> {
+ PrintStream out = null;
+ try {
+ // jeder Thread bekommt garantiert seinen eigenen PrintStream
+ out = new PrintStream(Thread.currentThread().threadId() + ".log");
+ } catch (FileNotFoundException e) {
+ // Abbruch mit Runtime statt Checked Exception:
+ throw new RuntimeException(e);
+ }
+ return new SimpleLoggerUnsafe(Logging.Severity.Warning, out);
+ });
+
+ @Override
+ public void log(Severity level, String msg) {
+ logger.get().log(level, msg);
+ }
+
+ @Override
+ public void flush() {
+ logger.get().flush();
+ }
+
+ @Override
+ public void setSeverityLevel(Severity level) {
+ logger.get().setSeverityLevel(level);
+ }
+
+ @Override
+ public Severity getSeverityLevel() {
+ return logger.get().getSeverityLevel();
+ }
+
+ @Override
+ public void setPrintStream(PrintStream out) {
+ // Threads könnten denselben PrintStream verwenden. Damit das nicht
+ // passiert, wird diese Methode "abgeschaltet".
+ throw new RuntimeException(new OperationNotSupportedException());
+ }
+}