diff --git a/src/pp.04.01-RunnableReturn/README.md b/src/pp.04.01-RunnableReturn/README.md new file mode 100644 index 0000000..3fa85f7 --- /dev/null +++ b/src/pp.04.01-RunnableReturn/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Thread für ``Runnable`` mit Rückgabewert" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-01-RunnableWithResult.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-thread-für-runnable-mit-rückgabewert) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.04.01-RunnableReturn_solution/README.md b/src/pp.04.01-RunnableReturn_solution/README.md new file mode 100644 index 0000000..3fa85f7 --- /dev/null +++ b/src/pp.04.01-RunnableReturn_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Thread für ``Runnable`` mit Rückgabewert" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-01-RunnableWithResult.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-thread-für-runnable-mit-rückgabewert) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.04.02-Future/README.md b/src/pp.04.02-Future/README.md new file mode 100644 index 0000000..bd2c085 --- /dev/null +++ b/src/pp.04.02-Future/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Asynchrone Ausführung mit ``Callable`` und ``Future``" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-02-Future.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-asynchrone-ausführung-mit-callable-und-future) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.04.02-Future_solution/README.md b/src/pp.04.02-Future_solution/README.md new file mode 100644 index 0000000..bd2c085 --- /dev/null +++ b/src/pp.04.02-Future_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Asynchrone Ausführung mit ``Callable`` und ``Future``" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-02-Future.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-asynchrone-ausführung-mit-callable-und-future) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.04.03-ThreadPoolSize/README.md b/src/pp.04.03-ThreadPoolSize/README.md new file mode 100644 index 0000000..3a03d3a --- /dev/null +++ b/src/pp.04.03-ThreadPoolSize/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Thread Pools" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-03-ThreadPoolSize.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-thread-pools) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.04.03-ThreadPoolSize_solution/README.md b/src/pp.04.03-ThreadPoolSize_solution/README.md new file mode 100644 index 0000000..3a03d3a --- /dev/null +++ b/src/pp.04.03-ThreadPoolSize_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Thread Pools" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-03-ThreadPoolSize.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/04-Solutions.html#laboraufgabe-thread-pools) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/04-threadpools.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/04-threadpools.html) diff --git a/src/pp.05.01-CounterAtomic/README.md b/src/pp.05.01-CounterAtomic/README.md new file mode 100644 index 0000000..ec96a93 --- /dev/null +++ b/src/pp.05.01-CounterAtomic/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Counter mit Atomics threadsicher machen" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/05-01-CounterAtomic.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/05-Solutions.html#laboraufgabe-counter-mit-atomics-threadsicher-machen) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/05-atomics.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/05-atomics.html) diff --git a/src/pp.05.01-CounterAtomic/justfile b/src/pp.05.01-CounterAtomic/justfile new file mode 100644 index 0000000..43d3962 --- /dev/null +++ b/src/pp.05.01-CounterAtomic/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile test +exec args: + mvn exec:java -Dexec.args={{args}} +clean: + mvn clean +compile: + mvn compile +test: + mvn test +javadoc: + mvn javadoc:javadoc diff --git a/src/pp.05.01-CounterAtomic/pom.xml b/src/pp.05.01-CounterAtomic/pom.xml new file mode 100644 index 0000000..29d7273 --- /dev/null +++ b/src/pp.05.01-CounterAtomic/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + pp + pp.05.01-CounterAtomic + 1.0-SNAPSHOT + jar + + + 10 + UTF-8 + + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + org.projectlombok + lombok + 1.18.30 + provided + + + net.jcip + jcip-annotations + 1.0 + provided + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.9.0 + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.5.0 + + private + en_US + + + + + diff --git a/src/pp.05.01-CounterAtomic/src/main/java/pp/Counter.java b/src/pp.05.01-CounterAtomic/src/main/java/pp/Counter.java new file mode 100644 index 0000000..ce619a1 --- /dev/null +++ b/src/pp.05.01-CounterAtomic/src/main/java/pp/Counter.java @@ -0,0 +1,22 @@ +package pp; + +class Counter { + private int c; + + public Counter(int init) { + this.c = init; + } + + public void inc() { + this.c++; + } + + public void dec() { + this.c--; + } + + public int get() { + return this.c; + } + +} diff --git a/src/pp.05.01-CounterAtomic/src/test/java/pp/CounterTest.java b/src/pp.05.01-CounterAtomic/src/test/java/pp/CounterTest.java new file mode 100644 index 0000000..79102d2 --- /dev/null +++ b/src/pp.05.01-CounterAtomic/src/test/java/pp/CounterTest.java @@ -0,0 +1,19 @@ +package pp; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class CounterTest { + + @Test + public void testInc() throws InterruptedException { + fail(); + } + + @Test + public void testDec() throws InterruptedException { + fail(); + } + +} diff --git a/src/pp.05.01-CounterAtomic_solution/README.md b/src/pp.05.01-CounterAtomic_solution/README.md new file mode 100644 index 0000000..ec96a93 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Counter mit Atomics threadsicher machen" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/05-01-CounterAtomic.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/05-Solutions.html#laboraufgabe-counter-mit-atomics-threadsicher-machen) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/05-atomics.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/05-atomics.html) diff --git a/src/pp.05.01-CounterAtomic_solution/justfile b/src/pp.05.01-CounterAtomic_solution/justfile new file mode 100644 index 0000000..43d3962 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile test +exec args: + mvn exec:java -Dexec.args={{args}} +clean: + mvn clean +compile: + mvn compile +test: + mvn test +javadoc: + mvn javadoc:javadoc diff --git a/src/pp.05.01-CounterAtomic_solution/pom.xml b/src/pp.05.01-CounterAtomic_solution/pom.xml new file mode 100644 index 0000000..2b5d6c9 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + pp + pp.05.01-CounterAtomic_solution + 1.0-SNAPSHOT + jar + + + 10 + UTF-8 + + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + org.projectlombok + lombok + 1.18.30 + provided + + + net.jcip + jcip-annotations + 1.0 + provided + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.9.0 + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.5.0 + + private + en_US + + + + + diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter1.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter1.java new file mode 100644 index 0000000..4d098bc --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter1.java @@ -0,0 +1,32 @@ +package pp; + +import java.util.concurrent.atomic.AtomicInteger; + +class AtomicCounter1 implements ICounter { + private final AtomicInteger c; + + public AtomicCounter1(int init) { + this.c = new AtomicInteger(init); + } + + @Override + public void inc() { + var temp = this.c.get(); + while (!this.c.compareAndSet(temp, temp + 1)) { + temp = this.c.get(); + } + } + + @Override + public void dec() { + var temp = this.c.get(); + while (!this.c.compareAndSet(temp, temp - 1)) { + temp = this.c.get(); + } + } + + @Override + public int get() { + return this.c.get(); + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter2.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter2.java new file mode 100644 index 0000000..8aecd91 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter2.java @@ -0,0 +1,26 @@ +package pp; + +import java.util.concurrent.atomic.AtomicInteger; + +class AtomicCounter2 implements ICounter { + private final AtomicInteger c; + + public AtomicCounter2(int init) { + this.c = new AtomicInteger(init); + } + + @Override + public void inc() { + this.c.incrementAndGet(); + } + + @Override + public void dec() { + this.c.decrementAndGet(); + } + + @Override + public int get() { + return this.c.get(); + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter3.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter3.java new file mode 100644 index 0000000..18b58cf --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter3.java @@ -0,0 +1,38 @@ +package pp; + +import java.util.concurrent.atomic.AtomicInteger; + +class AtomicCounter3 implements ICounter { + private final AtomicInteger c; + + public AtomicCounter3(int init) { + this.c = new AtomicInteger(init); + } + + @Override + public void inc() { + for (;;) { + var current = this.c.get(); + var next = current + 1; + if (this.c.compareAndSet(current, next)) { + break; + } + } + } + + @Override + public void dec() { + for (;;) { + var current = this.c.get(); + var next = current - 1; + if (this.c.compareAndSet(current, next)) { + break; + } + } + } + + @Override + public int get() { + return this.c.get(); + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter4.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter4.java new file mode 100644 index 0000000..04b3206 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/AtomicCounter4.java @@ -0,0 +1,26 @@ +package pp; + +import java.util.concurrent.atomic.AtomicInteger; + +class AtomicCounter4 implements ICounter { + private final AtomicInteger c; + + public AtomicCounter4(int init) { + this.c = new AtomicInteger(init); + } + + @Override + public void inc() { + this.c.updateAndGet(i -> i + 1); + } + + @Override + public void dec() { + this.c.updateAndGet(i -> i - 1); + } + + @Override + public int get() { + return this.c.get(); + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/Counter.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/Counter.java new file mode 100644 index 0000000..fc83ae7 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/Counter.java @@ -0,0 +1,24 @@ +package pp; + +class Counter implements ICounter { + private int c; + + public Counter(int init) { + this.c = init; + } + + @Override + public void inc() { + this.c++; + } + + @Override + public void dec() { + this.c--; + } + + @Override + public int get() { + return this.c; + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/ICounter.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/ICounter.java new file mode 100644 index 0000000..18b4caa --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/ICounter.java @@ -0,0 +1,11 @@ +package pp; + +interface ICounter { + + void inc(); + + void dec(); + + int get(); + +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/SynchronizedCounter.java b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/SynchronizedCounter.java new file mode 100644 index 0000000..050cf46 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/main/java/pp/SynchronizedCounter.java @@ -0,0 +1,24 @@ +package pp; + +class SynchronizedCounter implements ICounter { + private int c; + + public SynchronizedCounter(int init) { + this.c = init; + } + + @Override + public synchronized void inc() { + this.c++; + } + + @Override + public synchronized void dec() { + this.c--; + } + + @Override + public synchronized int get() { + return this.c; + } +} diff --git a/src/pp.05.01-CounterAtomic_solution/src/test/java/pp/CounterTest.java b/src/pp.05.01-CounterAtomic_solution/src/test/java/pp/CounterTest.java new file mode 100644 index 0000000..c791d09 --- /dev/null +++ b/src/pp.05.01-CounterAtomic_solution/src/test/java/pp/CounterTest.java @@ -0,0 +1,116 @@ +package pp; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class CounterTest { + private final static int RUNS = 500000; + + private static void testIncrement(ICounter counter) { + assertEquals(0, counter.get()); + var t1 = new Thread(() -> { + for (var j = 0; j < RUNS; j++) { + counter.inc(); + } + }); + var t2 = new Thread(() -> { + for (var j = 0; j < RUNS; j++) { + counter.inc(); + } + }); + t1.start(); + t2.start(); + try { + t1.join(); + t2.join(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + assertEquals(RUNS * 2, counter.get()); + } + + @Test + void testCounterIncrement() throws InterruptedException { + testIncrement(new Counter(0)); + } + + @Test + void testSynchronizedCounterIncrement() throws InterruptedException { + testIncrement(new SynchronizedCounter(0)); + } + + @Test + void testAtomicCounter1Increment() throws InterruptedException { + testIncrement(new AtomicCounter1(0)); + } + + @Test + void testAtomicCounter2Increment() throws InterruptedException { + testIncrement(new AtomicCounter2(0)); + } + + @Test + void testAtomicCounter3Increment() throws InterruptedException { + testIncrement(new AtomicCounter3(0)); + } + + @Test + void testAtomicCounter4Increment() throws InterruptedException { + testIncrement(new AtomicCounter4(0)); + } + + private static void testDecrement(ICounter counter) { + assertEquals(RUNS * 2, counter.get()); + var t1 = new Thread(() -> { + for (var j = 0; j < RUNS; j++) { + counter.dec(); + } + }); + var t2 = new Thread(() -> { + for (var j = 0; j < RUNS; j++) { + counter.dec(); + } + }); + t1.start(); + t2.start(); + try { + t1.join(); + t2.join(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + assertEquals(0, counter.get()); + } + + @Test + void testCounterDecrement() throws InterruptedException { + testDecrement(new Counter(RUNS * 2)); + } + + @Test + void testSynchronizedCounterDecrement() throws InterruptedException { + testDecrement(new SynchronizedCounter(RUNS * 2)); + } + + @Test + void testAtomicCounter1Decrement() throws InterruptedException { + testDecrement(new AtomicCounter1(RUNS * 2)); + } + + @Test + void testAtomicCounter2Decrement() throws InterruptedException { + testDecrement(new AtomicCounter2(RUNS * 2)); + } + + @Test + void testAtomicCounter3Decrement() throws InterruptedException { + testDecrement(new AtomicCounter3(RUNS * 2)); + } + + @Test + void testAtomicCounter4Decrement() throws InterruptedException { + testDecrement(new AtomicCounter4(RUNS * 2)); + } + +}