initial Kap. 10

main
Sandro Leuchter 2024-12-09 23:11:18 +01:00
parent 53803a654a
commit 7334686720
24 changed files with 1094 additions and 0 deletions

View File

@ -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)

View File

@ -0,0 +1,69 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pp</groupId>
<artifactId>pp.10.00-Exchanger</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.release>10</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile test</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,30 @@
package pp;
import net.jcip.annotations.ThreadSafe;
@ThreadSafe
public class SimpleExchanger<T> {
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;
}
}
}
}
}

View File

@ -0,0 +1,66 @@
package pp;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class ExchangerTest {
final private SimpleExchanger<Integer> 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();
}
}

View File

@ -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)

View File

@ -0,0 +1,72 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pp</groupId>
<artifactId>pp.10.01.Rendezvous</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>io.dama.ffi.rendezvous.Sum</exec.mainClass>
<maven.compiler.release>10</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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) {
}
}

View File

@ -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)

View File

@ -0,0 +1,72 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pp</groupId>
<artifactId>pp.10.01.Rendezvous_solution</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<exec.mainClass>pp.Sum</exec.mainClass>
<maven.compiler.release>10</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile exec:java</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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<Integer> o,
BlockingQueue<Integer> r, BlockingQueue<Boolean> 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<Integer> o, BlockingQueue<Integer> 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<Integer>();
var result = new LinkedBlockingQueue<Integer>();
var done = new LinkedBlockingQueue<Boolean>();
(new Thread(() -> tasker(1, 2, operand, result, done))).start();
(new Thread(() -> add(operand, result))).start();
done.take();
}
}

View File

@ -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)

View File

@ -0,0 +1,71 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pp</groupId>
<artifactId>pp.10.02.Logger</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>19</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,37 @@
package pp;
import java.io.PrintStream;
public class ThreadLocalLogger implements Logging {
private ThreadLocal<Logging> logger = ThreadLocal.withInitial(() -> {
// hier programmieren und ein ThreadLocal<Logging> 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);
}
}

View File

@ -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)

View File

@ -0,0 +1,71 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pp</groupId>
<artifactId>pp.10.02.Logger_solution</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>19</maven.compiler.release>
<lombok.version>edge-SNAPSHOT</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency><!-- für Unit-Tests -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency><!-- für Lombok -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency><!-- für net.jcip Annotationen -->
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean compile</defaultGoal>
<plugins>
<plugin><!-- für Unit-Tests [mvn test] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin><!-- [mvn compile] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin><!-- [mvn exec:java] -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin><!-- [mvn javadoc:javadoc] -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<locale>en_US</locale>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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();
}

View File

@ -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<String> queueDebug;
private final BlockingQueue<String> queueInfo;
private final BlockingQueue<String> queueNotice;
private final BlockingQueue<String> queueWarning;
private final BlockingQueue<String> queueError;
private final BlockingQueue<String> queueCritical;
private final BlockingQueue<String> queueAlert;
private final BlockingQueue<String> 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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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<Logging> 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());
}
}