forked from Parallele_Programmierung/Labs
initial Kap. 10
parent
53803a654a
commit
7334686720
|
|
@ -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)
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue