diff --git a/src/pp.01.01-Inheritance/src/main/java/pp/Sensor.java b/src/pp.01.01-Inheritance/src/main/java/pp/Sensor.java index 77652b3..bca5e97 100644 --- a/src/pp.01.01-Inheritance/src/main/java/pp/Sensor.java +++ b/src/pp.01.01-Inheritance/src/main/java/pp/Sensor.java @@ -1,40 +1,41 @@ -package pp; - -public class Sensor extends Thread { - // eigentlich abstract - - private final long frequency; - - public Sensor(long frequency) { - this.frequency = frequency; - start(); - } - - /** - * @return the frequency - */ - public long getFrequency() { - return this.frequency; - } - - protected String reading() { - // eigentlich abstract - return null; - } - - @Override - public void run() { - while (true) { - System.out.println("reading: " + reading()); - try { - Thread.sleep(this.frequency); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - - public static void main(String... args) { - var s = new Sensor(1000); - } -} +package pp; + +public class Sensor extends Thread { + + // eigentlich abstract + + private final long frequency; + + public Sensor(long frequency) { + this.frequency = frequency; + start(); + } + + /** + * @return the frequency + */ + public long getFrequency() { + return this.frequency; + } + + protected String reading() { + // eigentlich abstract + return null; + } + + @Override + public void run() { + while (true) { + System.out.println("reading: " + reading()); + try { + Thread.sleep(this.frequency); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + public static void main(String... args) { + var s = new Sensor(1000); + } +} diff --git a/src/pp.01.01-Inheritance/src/main/java/pp/Thermometer.java b/src/pp.01.01-Inheritance/src/main/java/pp/Thermometer.java index 717f846..b823af0 100644 --- a/src/pp.01.01-Inheritance/src/main/java/pp/Thermometer.java +++ b/src/pp.01.01-Inheritance/src/main/java/pp/Thermometer.java @@ -1,23 +1,23 @@ -package pp; - -import java.util.Random; - -public class Thermometer extends Sensor { - private final Random rand; - - public Thermometer(long frequency) { - super(frequency); - this.rand = new Random(); - } - - @Override - protected String reading() { - return String.format("(%04d freq.): %3d°C", getFrequency(), - this.rand.nextInt(100)); - } - - public static void main(String... args) { - var s1 = new Thermometer(1000); - var s2 = new Thermometer(3000); - } -} +package pp; + +import java.util.Random; + +public class Thermometer extends Sensor { + + private final Random rand; + + public Thermometer(long frequency) { + super(frequency); + this.rand = new Random(); + } + + @Override + protected String reading() { + return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100)); + } + + public static void main(String... args) { + var s1 = new Thermometer(1000); + var s2 = new Thermometer(3000); + } +} diff --git a/src/pp.01.01-Inheritance_solution/src/main/java/pp/Sensor.java b/src/pp.01.01-Inheritance_solution/src/main/java/pp/Sensor.java index fdae6bc..08655a7 100644 --- a/src/pp.01.01-Inheritance_solution/src/main/java/pp/Sensor.java +++ b/src/pp.01.01-Inheritance_solution/src/main/java/pp/Sensor.java @@ -1,40 +1,41 @@ -package pp; - -public class Sensor extends Thread { - // eigentlich abstract - - private final long frequency; - - public Sensor(long frequency) { - this.frequency = frequency; - } - - /** - * @return the frequency - */ - public long getFrequency() { - return this.frequency; - } - - protected String reading() { - // eigentlich abstract - return null; - } - - @Override - public void run() { - while (true) { - System.out.println("reading: " + reading()); - try { - Thread.sleep(this.frequency); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - - public static void main(String... args) { - var s = new Sensor(1000); - s.start(); - } -} +package pp; + +public class Sensor extends Thread { + + // eigentlich abstract + + private final long frequency; + + public Sensor(long frequency) { + this.frequency = frequency; + } + + /** + * @return the frequency + */ + public long getFrequency() { + return this.frequency; + } + + protected String reading() { + // eigentlich abstract + return null; + } + + @Override + public void run() { + while (true) { + System.out.println("reading: " + reading()); + try { + Thread.sleep(this.frequency); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + public static void main(String... args) { + var s = new Sensor(1000); + s.start(); + } +} diff --git a/src/pp.01.01-Inheritance_solution/src/main/java/pp/Thermometer.java b/src/pp.01.01-Inheritance_solution/src/main/java/pp/Thermometer.java index fbbb6bc..76042c9 100644 --- a/src/pp.01.01-Inheritance_solution/src/main/java/pp/Thermometer.java +++ b/src/pp.01.01-Inheritance_solution/src/main/java/pp/Thermometer.java @@ -1,25 +1,25 @@ -package pp; - -import java.util.Random; - -public class Thermometer extends Sensor { - private final Random rand; - - public Thermometer(long frequency) { - super(frequency); - this.rand = new Random(); - } - - @Override - protected String reading() { - return String.format("(%04d freq.): %3d°C", getFrequency(), - this.rand.nextInt(100)); - } - - public static void main(String... args) { - var s1 = new Thermometer(1000); - s1.start(); - var s2 = new Thermometer(3000); - s2.start(); - } -} +package pp; + +import java.util.Random; + +public class Thermometer extends Sensor { + + private final Random rand; + + public Thermometer(long frequency) { + super(frequency); + this.rand = new Random(); + } + + @Override + protected String reading() { + return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100)); + } + + public static void main(String... args) { + var s1 = new Thermometer(1000); + s1.start(); + var s2 = new Thermometer(3000); + s2.start(); + } +} diff --git a/src/pp.01.02-Runnable/src/main/java/pp/MyWorker.java b/src/pp.01.02-Runnable/src/main/java/pp/MyWorker.java index 4a2cb02..7225f95 100644 --- a/src/pp.01.02-Runnable/src/main/java/pp/MyWorker.java +++ b/src/pp.01.02-Runnable/src/main/java/pp/MyWorker.java @@ -1,14 +1,14 @@ -package pp; - -class MyWorker implements Runnable { - private Thread self; - - @Override - public void run() { - this.self = Thread.currentThread(); - while (true) { - System.out.println( - this.self.getName() + ": ID => " + this.self.threadId()); - } - } -} +package pp; + +class MyWorker implements Runnable { + + private Thread self; + + @Override + public void run() { + this.self = Thread.currentThread(); + while (true) { + System.out.println(this.self.getName() + ": ID => " + this.self.threadId()); + } + } +} diff --git a/src/pp.01.02-Runnable/src/main/java/pp/MyWorkerCoop.java b/src/pp.01.02-Runnable/src/main/java/pp/MyWorkerCoop.java index 869952c..19425c9 100644 --- a/src/pp.01.02-Runnable/src/main/java/pp/MyWorkerCoop.java +++ b/src/pp.01.02-Runnable/src/main/java/pp/MyWorkerCoop.java @@ -1,15 +1,15 @@ -package pp; - -class MyWorkerCoop implements Runnable { - private Thread self; - - @Override - public void run() { - this.self = Thread.currentThread(); - while (true) { - System.out.println( - this.self.getName() + ": ID => " + this.self.threadId()); - Thread.yield(); - } - } -} +package pp; + +class MyWorkerCoop implements Runnable { + + private Thread self; + + @Override + public void run() { + this.self = Thread.currentThread(); + while (true) { + System.out.println(this.self.getName() + ": ID => " + this.self.threadId()); + Thread.yield(); + } + } +} diff --git a/src/pp.01.02-Runnable/src/main/java/pp/Starter.java b/src/pp.01.02-Runnable/src/main/java/pp/Starter.java index b450b20..7df7525 100644 --- a/src/pp.01.02-Runnable/src/main/java/pp/Starter.java +++ b/src/pp.01.02-Runnable/src/main/java/pp/Starter.java @@ -1,12 +1,13 @@ -package pp; - -public class Starter { - static int WORKERS = 200; - - public static void main(String... args) { - for (var i = 0; i < Starter.WORKERS; i++) { - var t = new Thread(new MyWorker(), String.format("Worker-%03d", i)); - t.start(); - } - } -} +package pp; + +public class Starter { + + static int WORKERS = 200; + + public static void main(String... args) { + for (var i = 0; i < Starter.WORKERS; i++) { + var t = new Thread(new MyWorker(), String.format("Worker-%03d", i)); + t.start(); + } + } +} diff --git a/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorker.java b/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorker.java index 4a2cb02..7225f95 100644 --- a/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorker.java +++ b/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorker.java @@ -1,14 +1,14 @@ -package pp; - -class MyWorker implements Runnable { - private Thread self; - - @Override - public void run() { - this.self = Thread.currentThread(); - while (true) { - System.out.println( - this.self.getName() + ": ID => " + this.self.threadId()); - } - } -} +package pp; + +class MyWorker implements Runnable { + + private Thread self; + + @Override + public void run() { + this.self = Thread.currentThread(); + while (true) { + System.out.println(this.self.getName() + ": ID => " + this.self.threadId()); + } + } +} diff --git a/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorkerCoop.java b/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorkerCoop.java index 869952c..19425c9 100644 --- a/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorkerCoop.java +++ b/src/pp.01.02-Runnable_solution/src/main/java/pp/MyWorkerCoop.java @@ -1,15 +1,15 @@ -package pp; - -class MyWorkerCoop implements Runnable { - private Thread self; - - @Override - public void run() { - this.self = Thread.currentThread(); - while (true) { - System.out.println( - this.self.getName() + ": ID => " + this.self.threadId()); - Thread.yield(); - } - } -} +package pp; + +class MyWorkerCoop implements Runnable { + + private Thread self; + + @Override + public void run() { + this.self = Thread.currentThread(); + while (true) { + System.out.println(this.self.getName() + ": ID => " + this.self.threadId()); + Thread.yield(); + } + } +} diff --git a/src/pp.01.02-Runnable_solution/src/main/java/pp/Starter.java b/src/pp.01.02-Runnable_solution/src/main/java/pp/Starter.java index 17e77bf..2e3b988 100644 --- a/src/pp.01.02-Runnable_solution/src/main/java/pp/Starter.java +++ b/src/pp.01.02-Runnable_solution/src/main/java/pp/Starter.java @@ -1,13 +1,13 @@ -package pp; - -public class Starter { - static int WORKERS = 200; - - public static void main(String... args) { - for (var i = 0; i < Starter.WORKERS; i++) { - var t = new Thread(new MyWorkerCoop(), - String.format("Worker-%03d", i)); - t.start(); - } - } -} +package pp; + +public class Starter { + + static int WORKERS = 200; + + public static void main(String... args) { + for (var i = 0; i < Starter.WORKERS; i++) { + var t = new Thread(new MyWorkerCoop(), String.format("Worker-%03d", i)); + t.start(); + } + } +} diff --git a/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterInner.java b/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterInner.java index 0d41f6f..8015250 100644 --- a/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterInner.java +++ b/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterInner.java @@ -1,23 +1,26 @@ -package pp; - -public class StarterInner { - static int WORKERS = 200; - - public static void main(String... args) { - for (var i = 0; i < StarterInner.WORKERS; i++) { - var t = new Thread(new Runnable() { - private Thread self; - - @Override - public void run() { - this.self = Thread.currentThread(); - while (true) { - System.out.println(this.self.getName() + ": ID => " - + this.self.threadId()); - } - } - }, String.format("Worker-%03d", i)); - t.start(); - } - } -} +package pp; + +public class StarterInner { + + static int WORKERS = 200; + + public static void main(String... args) { + for (var i = 0; i < StarterInner.WORKERS; i++) { + var t = new Thread( + new Runnable() { + private Thread self; + + @Override + public void run() { + this.self = Thread.currentThread(); + while (true) { + System.out.println(this.self.getName() + ": ID => " + this.self.threadId()); + } + } + }, + String.format("Worker-%03d", i) + ); + t.start(); + } + } +} diff --git a/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterLambda.java b/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterLambda.java index e12d3f6..d3968bf 100644 --- a/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterLambda.java +++ b/src/pp.01.02-Runnable_solution/src/main/java/pp/StarterLambda.java @@ -1,18 +1,21 @@ -package pp; - -public class StarterLambda { - static int WORKERS = 200; - - public static void main(String... args) { - for (var i = 0; i < StarterLambda.WORKERS; i++) { - var t = new Thread(() -> { - var self = Thread.currentThread(); - while (true) { - System.out.println( - self.getName() + ": ID => " + self.threadId()); - } - }, String.format("Worker-%03d", i)); - t.start(); - } - } -} +package pp; + +public class StarterLambda { + + static int WORKERS = 200; + + public static void main(String... args) { + for (var i = 0; i < StarterLambda.WORKERS; i++) { + var t = new Thread( + () -> { + var self = Thread.currentThread(); + while (true) { + System.out.println(self.getName() + ": ID => " + self.threadId()); + } + }, + String.format("Worker-%03d", i) + ); + t.start(); + } + } +} diff --git a/src/pp.01.03-EndThread/src/main/java/pp/Runner.java b/src/pp.01.03-EndThread/src/main/java/pp/Runner.java index af67c76..7123a5e 100644 --- a/src/pp.01.03-EndThread/src/main/java/pp/Runner.java +++ b/src/pp.01.03-EndThread/src/main/java/pp/Runner.java @@ -1,15 +1,16 @@ -package pp; - -public class Runner { - public static void main(String... args) { - var task = new Task(); - var thread = new Thread(task); - thread.setUncaughtExceptionHandler((t, e) -> { - System.err.println("Unhandled Exception: " + e.getMessage()); - System.err.println(" Thread: " + t.threadId() + " - " + t.getName()); - System.err.println(" Thread State: " + t.getState()); - e.printStackTrace(System.err); - }); - thread.start(); - } -} +package pp; + +public class Runner { + + public static void main(String... args) { + var task = new Task(); + var thread = new Thread(task); + thread.setUncaughtExceptionHandler((t, e) -> { + System.err.println("Unhandled Exception: " + e.getMessage()); + System.err.println(" Thread: " + t.threadId() + " - " + t.getName()); + System.err.println(" Thread State: " + t.getState()); + e.printStackTrace(System.err); + }); + thread.start(); + } +} diff --git a/src/pp.01.03-EndThread/src/main/java/pp/Task.java b/src/pp.01.03-EndThread/src/main/java/pp/Task.java index bf44a60..d997273 100644 --- a/src/pp.01.03-EndThread/src/main/java/pp/Task.java +++ b/src/pp.01.03-EndThread/src/main/java/pp/Task.java @@ -1,35 +1,36 @@ -package pp; - -public class Task implements Runnable { - private volatile Thread self; - private volatile boolean stopped = false; - - public void stopRequest() { - this.stopped = true; - if (this.self != null) { - this.self.interrupt(); - } - } - - public boolean isStopped() { - return this.stopped; - } - - @Override - public void run() { - this.self = Thread.currentThread(); - // 1. Initialisierungsphase - var i = 10; - while (!isStopped()) { - // 2. Arbeitsphase - System.out.println("i=" + i); - try { - Thread.sleep(1000 / i--); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - // 3. Aufräumphase - System.out.println("fertig."); - } -} +package pp; + +public class Task implements Runnable { + + private volatile Thread self; + private volatile boolean stopped = false; + + public void stopRequest() { + this.stopped = true; + if (this.self != null) { + this.self.interrupt(); + } + } + + public boolean isStopped() { + return this.stopped; + } + + @Override + public void run() { + this.self = Thread.currentThread(); + // 1. Initialisierungsphase + var i = 10; + while (!isStopped()) { + // 2. Arbeitsphase + System.out.println("i=" + i); + try { + Thread.sleep(1000 / i--); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + // 3. Aufräumphase + System.out.println("fertig."); + } +} diff --git a/src/pp.01.03-EndThread_solution/src/main/java/pp/Runner.java b/src/pp.01.03-EndThread_solution/src/main/java/pp/Runner.java index 7b61e20..fcb444e 100644 --- a/src/pp.01.03-EndThread_solution/src/main/java/pp/Runner.java +++ b/src/pp.01.03-EndThread_solution/src/main/java/pp/Runner.java @@ -1,20 +1,21 @@ -package pp; - -public class Runner { - public static void main(String... args) { - var task = new Task(); - var thread = new Thread(task); - thread.setUncaughtExceptionHandler((t, e) -> { - System.err.println("Unhandled Exception: " + e.getMessage()); - System.err.println(" Thread: " + t.threadId() + " - " + t.getName()); - System.err.println(" Thread State: " + t.getState()); - e.printStackTrace(System.err); - }); - thread.start(); - // falsch: thread läuft weiter: - // (new Thread(() -> thread.interrupt())).start(); - - // richtig: thread wird beendet: - (new Thread(() -> task.stopRequest())).start(); - } -} +package pp; + +public class Runner { + + public static void main(String... args) { + var task = new Task(); + var thread = new Thread(task); + thread.setUncaughtExceptionHandler((t, e) -> { + System.err.println("Unhandled Exception: " + e.getMessage()); + System.err.println(" Thread: " + t.threadId() + " - " + t.getName()); + System.err.println(" Thread State: " + t.getState()); + e.printStackTrace(System.err); + }); + thread.start(); + // falsch: thread läuft weiter: + // (new Thread(() -> thread.interrupt())).start(); + + // richtig: thread wird beendet: + (new Thread(() -> task.stopRequest())).start(); + } +} diff --git a/src/pp.01.03-EndThread_solution/src/main/java/pp/Task.java b/src/pp.01.03-EndThread_solution/src/main/java/pp/Task.java index bf44a60..d997273 100644 --- a/src/pp.01.03-EndThread_solution/src/main/java/pp/Task.java +++ b/src/pp.01.03-EndThread_solution/src/main/java/pp/Task.java @@ -1,35 +1,36 @@ -package pp; - -public class Task implements Runnable { - private volatile Thread self; - private volatile boolean stopped = false; - - public void stopRequest() { - this.stopped = true; - if (this.self != null) { - this.self.interrupt(); - } - } - - public boolean isStopped() { - return this.stopped; - } - - @Override - public void run() { - this.self = Thread.currentThread(); - // 1. Initialisierungsphase - var i = 10; - while (!isStopped()) { - // 2. Arbeitsphase - System.out.println("i=" + i); - try { - Thread.sleep(1000 / i--); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - // 3. Aufräumphase - System.out.println("fertig."); - } -} +package pp; + +public class Task implements Runnable { + + private volatile Thread self; + private volatile boolean stopped = false; + + public void stopRequest() { + this.stopped = true; + if (this.self != null) { + this.self.interrupt(); + } + } + + public boolean isStopped() { + return this.stopped; + } + + @Override + public void run() { + this.self = Thread.currentThread(); + // 1. Initialisierungsphase + var i = 10; + while (!isStopped()) { + // 2. Arbeitsphase + System.out.println("i=" + i); + try { + Thread.sleep(1000 / i--); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + // 3. Aufräumphase + System.out.println("fertig."); + } +} diff --git a/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java b/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java index a84d21a..5f592d1 100644 --- a/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java +++ b/src/pp.02.01-MemoryBarrier/src/main/java/pp/MemoryBarrierTest.java @@ -1,24 +1,22 @@ -package pp; - -public class MemoryBarrierTest extends Thread { - - public boolean stopped = false; - - @Override - public void run() { - while (!this.stopped) { - // work - } - System.out.println("MemoryBarrierTest-Thread actually stopped."); - } - - public static void main(String... args) throws InterruptedException { - var t = new MemoryBarrierTest(); - t.start(); - Thread.sleep(1000); - t.stopped = true; - System.out.println( - "Main thread set stopped on MemoryBarrierTest-Thread."); - } - -} +package pp; + +public class MemoryBarrierTest extends Thread { + + public boolean stopped = false; + + @Override + public void run() { + while (!this.stopped) { + // work + } + System.out.println("MemoryBarrierTest-Thread actually stopped."); + } + + public static void main(String... args) throws InterruptedException { + var t = new MemoryBarrierTest(); + t.start(); + Thread.sleep(1000); + t.stopped = true; + System.out.println("Main thread set stopped on MemoryBarrierTest-Thread."); + } +} diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java index 9c06da0..0273560 100644 --- a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java +++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1.java @@ -1,26 +1,24 @@ -package pp; - -public class MemoryBarrierTest1 extends Thread { - - // Markierung von stopped als volatile => Jede Änderung wirkt als - // Memory-Barrier - public volatile boolean stopped = false; - - @Override - public void run() { - while (!this.stopped) { - // work - } - System.out.println("MemoryBarrierTest-Thread actually stopped."); - } - - public static void main(String... args) throws InterruptedException { - var t = new MemoryBarrierTest1(); - t.start(); - Thread.sleep(1000); - t.stopped = true; - System.out.println( - "Main thread set stopped on MemoryBarrierTest-Thread."); - } - -} +package pp; + +public class MemoryBarrierTest1 extends Thread { + + // Markierung von stopped als volatile => Jede Änderung wirkt als + // Memory-Barrier + public volatile boolean stopped = false; + + @Override + public void run() { + while (!this.stopped) { + // work + } + System.out.println("MemoryBarrierTest-Thread actually stopped."); + } + + public static void main(String... args) throws InterruptedException { + var t = new MemoryBarrierTest1(); + t.start(); + Thread.sleep(1000); + t.stopped = true; + System.out.println("Main thread set stopped on MemoryBarrierTest-Thread."); + } +} diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java index b8c8451..5cf9505 100644 --- a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java +++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest1b.java @@ -29,8 +29,6 @@ public class MemoryBarrierTest1b extends Thread { t.start(); Thread.sleep(1000); t.setStopped(true); - System.out.println( - "Main thread set stopped on MemoryBarrierTest-Thread."); + System.out.println("Main thread set stopped on MemoryBarrierTest-Thread."); } - } diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java index dbbf523..994a1e5 100644 --- a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java +++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest2.java @@ -1,28 +1,26 @@ -package pp; - -public class MemoryBarrierTest2 extends Thread { - - public boolean stopped = false; - - @Override - public void run() { - while (!this.stopped) { - // jedes synchronized wirkt als Memory-Barrier - // work - synchronized (this) { - // - } - } - System.out.println("MemoryBarrierTest-Thread actually stopped."); - } - - public static void main(String... args) throws InterruptedException { - var t = new MemoryBarrierTest2(); - t.start(); - Thread.sleep(1000); - t.stopped = true; - System.out.println( - "Main thread set stopped on MemoryBarrierTest-Thread."); - } - -} +package pp; + +public class MemoryBarrierTest2 extends Thread { + + public boolean stopped = false; + + @Override + public void run() { + while (!this.stopped) { + // jedes synchronized wirkt als Memory-Barrier + // work + synchronized (this) { + // + } + } + System.out.println("MemoryBarrierTest-Thread actually stopped."); + } + + public static void main(String... args) throws InterruptedException { + var t = new MemoryBarrierTest2(); + t.start(); + Thread.sleep(1000); + t.stopped = true; + System.out.println("Main thread set stopped on MemoryBarrierTest-Thread."); + } +} diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java index 6be5da0..4381339 100644 --- a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java +++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest5.java @@ -13,8 +13,7 @@ public class MemoryBarrierTest5 extends Thread { Thread.currentThread().interrupt(); } this.stopped = true; - System.out.println( - "Stopper thread set stopped on MemoryBarrierTest-Thread."); + System.out.println("Stopper thread set stopped on MemoryBarrierTest-Thread."); }); this.stopper.start(); } @@ -40,7 +39,5 @@ public class MemoryBarrierTest5 extends Thread { public static void main(String... args) throws InterruptedException { var t = new MemoryBarrierTest5(); t.start(); - } - } diff --git a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java index 05e8d5c..e2a1349 100644 --- a/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java +++ b/src/pp.02.01-MemoryBarrier_solution/src/main/java/pp/MemoryBarrierTest6.java @@ -1,30 +1,28 @@ -package pp; - -public class MemoryBarrierTest6 extends Thread { - - public boolean stopped = false; - - @Override - public void run() { - while (!this.stopped) { - // work - // wg. Zustandswechsel - try { - Thread.sleep(1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - System.out.println("MemoryBarrierTest-Thread actually stopped."); - } - - public static void main(String... args) throws InterruptedException { - var t = new MemoryBarrierTest6(); - t.start(); - Thread.sleep(1000); - t.stopped = true; - System.out.println( - "Main thread set stopped on MemoryBarrierTest-Thread."); - } - -} +package pp; + +public class MemoryBarrierTest6 extends Thread { + + public boolean stopped = false; + + @Override + public void run() { + while (!this.stopped) { + // work + // wg. Zustandswechsel + try { + Thread.sleep(1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + System.out.println("MemoryBarrierTest-Thread actually stopped."); + } + + public static void main(String... args) throws InterruptedException { + var t = new MemoryBarrierTest6(); + t.start(); + Thread.sleep(1000); + t.stopped = true; + System.out.println("Main thread set stopped on MemoryBarrierTest-Thread."); + } +} diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java index 32fb4d8..e8dd17c 100644 --- a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java +++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom0.java @@ -1,25 +1,26 @@ -package pp; - -import java.util.Random; - -public class MyThreadLocalRandom0 implements Runnable { - public static long now = System.currentTimeMillis(); - public Random rand = new Random(now); - - @Override - public void run() { - var strBuf = new StringBuffer(); - strBuf.append(Thread.currentThread().getName() + ": "); - for (var j = 0; j < 20; j++) { - strBuf.append(String.format("%02d ", this.rand.nextInt(100))); - } - System.out.println(strBuf); - } - - public static void main(String... args) { - var runner = new MyThreadLocalRandom0(); - for (var i = 0; i < 10; i++) { - new Thread(runner, String.format("Runner-%02d", i)).start(); - } - } -} +package pp; + +import java.util.Random; + +public class MyThreadLocalRandom0 implements Runnable { + + public static long now = System.currentTimeMillis(); + public Random rand = new Random(now); + + @Override + public void run() { + var strBuf = new StringBuffer(); + strBuf.append(Thread.currentThread().getName() + ": "); + for (var j = 0; j < 20; j++) { + strBuf.append(String.format("%02d ", this.rand.nextInt(100))); + } + System.out.println(strBuf); + } + + public static void main(String... args) { + var runner = new MyThreadLocalRandom0(); + for (var i = 0; i < 10; i++) { + new Thread(runner, String.format("Runner-%02d", i)).start(); + } + } +} diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java index 53129de..af5e272 100644 --- a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java +++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom1.java @@ -1,30 +1,31 @@ -package pp; - -import java.util.Random; - -public class MyThreadLocalRandom1 implements Runnable { - public static long now = System.currentTimeMillis(); - public ThreadLocal rand = new ThreadLocal<>() { - @Override - protected Random initialValue() { - return new Random(now); - } - }; - - @Override - public void run() { - var strBuf = new StringBuffer(); - strBuf.append(Thread.currentThread().getName() + ": "); - for (var j = 0; j < 20; j++) { - strBuf.append(String.format("%02d ", this.rand.get().nextInt(100))); - } - System.out.println(strBuf); - } - - public static void main(String... args) { - var runner = new MyThreadLocalRandom1(); - for (var i = 0; i < 10; i++) { - new Thread(runner, String.format("Runner-%02d", i)).start(); - } - } -} +package pp; + +import java.util.Random; + +public class MyThreadLocalRandom1 implements Runnable { + + public static long now = System.currentTimeMillis(); + public ThreadLocal rand = new ThreadLocal<>() { + @Override + protected Random initialValue() { + return new Random(now); + } + }; + + @Override + public void run() { + var strBuf = new StringBuffer(); + strBuf.append(Thread.currentThread().getName() + ": "); + for (var j = 0; j < 20; j++) { + strBuf.append(String.format("%02d ", this.rand.get().nextInt(100))); + } + System.out.println(strBuf); + } + + public static void main(String... args) { + var runner = new MyThreadLocalRandom1(); + for (var i = 0; i < 10; i++) { + new Thread(runner, String.format("Runner-%02d", i)).start(); + } + } +} diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java index 9276a3a..0cc7890 100644 --- a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java +++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom2.java @@ -1,30 +1,31 @@ -package pp; - -import java.util.Random; - -public class MyThreadLocalRandom2 implements Runnable { - public static long now = System.currentTimeMillis(); - public static ThreadLocal rand = new ThreadLocal<>() { - @Override - protected Random initialValue() { - return new Random(now); - } - }; - - @Override - public void run() { - var strBuf = new StringBuffer(); - strBuf.append(Thread.currentThread().getName() + ": "); - for (var j = 0; j < 20; j++) { - strBuf.append(String.format("%02d ", rand.get().nextInt(100))); - } - System.out.println(strBuf); - } - - public static void main(String... args) { - var runner = new MyThreadLocalRandom2(); - for (var i = 0; i < 10; i++) { - new Thread(runner, String.format("Runner-%02d", i)).start(); - } - } -} +package pp; + +import java.util.Random; + +public class MyThreadLocalRandom2 implements Runnable { + + public static long now = System.currentTimeMillis(); + public static ThreadLocal rand = new ThreadLocal<>() { + @Override + protected Random initialValue() { + return new Random(now); + } + }; + + @Override + public void run() { + var strBuf = new StringBuffer(); + strBuf.append(Thread.currentThread().getName() + ": "); + for (var j = 0; j < 20; j++) { + strBuf.append(String.format("%02d ", rand.get().nextInt(100))); + } + System.out.println(strBuf); + } + + public static void main(String... args) { + var runner = new MyThreadLocalRandom2(); + for (var i = 0; i < 10; i++) { + new Thread(runner, String.format("Runner-%02d", i)).start(); + } + } +} diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java index caeac0c..39789c3 100644 --- a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java +++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom3.java @@ -1,28 +1,28 @@ -package pp; - -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -public class MyThreadLocalRandom3 implements Runnable { - - public static Random rand = ThreadLocalRandom.current(); - - @Override - public void run() { - var strBuf = new StringBuffer(); - strBuf.append(Thread.currentThread().getName() + ": "); - for (var j = 0; j < 20; j++) { - synchronized (MyThreadLocalRandom3.class) { - strBuf.append(String.format("%02d ", rand.nextInt(100))); - } - } - System.out.println(strBuf); - } - - public static void main(String... args) throws InterruptedException { - var runner = new MyThreadLocalRandom3(); - for (var i = 0; i < 10; i++) { - new Thread(runner, String.format("Runner-%02d", i)).start(); - } - } -} +package pp; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class MyThreadLocalRandom3 implements Runnable { + + public static Random rand = ThreadLocalRandom.current(); + + @Override + public void run() { + var strBuf = new StringBuffer(); + strBuf.append(Thread.currentThread().getName() + ": "); + for (var j = 0; j < 20; j++) { + synchronized (MyThreadLocalRandom3.class) { + strBuf.append(String.format("%02d ", rand.nextInt(100))); + } + } + System.out.println(strBuf); + } + + public static void main(String... args) throws InterruptedException { + var runner = new MyThreadLocalRandom3(); + for (var i = 0; i < 10; i++) { + new Thread(runner, String.format("Runner-%02d", i)).start(); + } + } +} diff --git a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java index 4e10b18..5cf0b04 100644 --- a/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java +++ b/src/pp.02.02-ThreadLocal_solution/src/main/java/pp/MyThreadLocalRandom4.java @@ -1,28 +1,28 @@ -package pp; - -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -public class MyThreadLocalRandom4 implements Runnable { - - public Random rand = ThreadLocalRandom.current(); - - @Override - public void run() { - var strBuf = new StringBuffer(); - strBuf.append(Thread.currentThread().getName() + ": "); - for (var j = 0; j < 20; j++) { - synchronized (MyThreadLocalRandom4.class) { - strBuf.append(String.format("%02d ", this.rand.nextInt(100))); - } - } - System.out.println(strBuf); - } - - public static void main(String... args) throws InterruptedException { - var runner = new MyThreadLocalRandom4(); - for (var i = 0; i < 10; i++) { - new Thread(runner, String.format("Runner-%02d", i)).start(); - } - } -} +package pp; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class MyThreadLocalRandom4 implements Runnable { + + public Random rand = ThreadLocalRandom.current(); + + @Override + public void run() { + var strBuf = new StringBuffer(); + strBuf.append(Thread.currentThread().getName() + ": "); + for (var j = 0; j < 20; j++) { + synchronized (MyThreadLocalRandom4.class) { + strBuf.append(String.format("%02d ", this.rand.nextInt(100))); + } + } + System.out.println(strBuf); + } + + public static void main(String... args) throws InterruptedException { + var runner = new MyThreadLocalRandom4(); + for (var i = 0; i < 10; i++) { + new Thread(runner, String.format("Runner-%02d", i)).start(); + } + } +} diff --git a/src/pp.02.03-Lock/src/main/java/pp/Factory.java b/src/pp.02.03-Lock/src/main/java/pp/Factory.java index 21332c6..aa9f3b8 100644 --- a/src/pp.02.03-Lock/src/main/java/pp/Factory.java +++ b/src/pp.02.03-Lock/src/main/java/pp/Factory.java @@ -21,9 +21,7 @@ public class Factory { () -> { Type object = Factory.getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java index b37dbdc..3489bce 100644 --- a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java +++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory0.java @@ -20,9 +20,7 @@ public class Factory0 { () -> { var object = getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java index 606fcc5..db4a2d1 100644 --- a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java +++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory1.java @@ -20,9 +20,7 @@ public class Factory1 { () -> { var object = getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java index a6dd570..0951262 100644 --- a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java +++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory2.java @@ -22,9 +22,7 @@ public class Factory2 { () -> { var object = getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java index df73dfc..69865ee 100644 --- a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java +++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory3.java @@ -23,9 +23,7 @@ public class Factory3 { () -> { var object = Factory3.getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java index 61c778a..a853306 100644 --- a/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java +++ b/src/pp.02.03-Lock_solution/src/main/java/pp/Factory4.java @@ -24,9 +24,7 @@ public class Factory4 { () -> { var object = getInstance(); System.out.println( - Thread.currentThread().getName() + - ": serial of instance = " + - object.getSerial() + Thread.currentThread().getName() + ": serial of instance = " + object.getSerial() ); }, String.format("InstanceGrabber-%02d", i) diff --git a/src/pp.03.01-SynchPhilosopher/README.md b/src/pp.03.01-SynchPhilosopher/README.md new file mode 100644 index 0000000..dc4f6d7 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Dinnierende Philosoph:innen" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-01-SynchPhilosopher.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-dinierende-philosophinnen) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.01-SynchPhilosopher/justfile b/src/pp.03.01-SynchPhilosopher/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.01-SynchPhilosopher/pom.xml b/src/pp.03.01-SynchPhilosopher/pom.xml new file mode 100644 index 0000000..6f69d87 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.01-SynchPhilosopher + 1.0-SNAPSHOT + jar + + + pp.PhilosopherExperiment + 19 + 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.03.01-SynchPhilosopher/src/main/java/pp/Chopstick.java b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/Chopstick.java new file mode 100644 index 0000000..1d14a3b --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/Chopstick.java @@ -0,0 +1,3 @@ +package pp; + +public class Chopstick {} diff --git a/src/pp.03.01-SynchPhilosopher/src/main/java/pp/Philosopher.java b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/Philosopher.java new file mode 100644 index 0000000..0dd1fdc --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/Philosopher.java @@ -0,0 +1,77 @@ +package pp; + +import java.util.Random; + +public class Philosopher extends Thread { + + static final int MAX_THINKING_DURATION_MS = 1000; + static final int MAX_EATING_DURATION_MS = 3000; + static final int MAX_TAKING_TIME_MS = 1000; + + private final Chopstick left; + private final Chopstick right; + private final Random random; + private int eaten; + private final int seat; + + private volatile boolean stop; + + private void log(String message) { + synchronized (Philosopher.class) { + for (var i = 1; i <= this.seat; i++) { + System.out.print(" "); + } + System.out.println(threadId() + " " + message); + } + } + + public void stopPhilosopher() { + log("stopping"); + this.stop = true; + interrupt(); + } + + public Philosopher(int seat, Chopstick left, Chopstick right) { + this.stop = false; + this.seat = seat; + this.left = left; + this.right = right; + this.random = new Random(); + this.eaten = 0; + } + + @Override + public void run() { + log("starting"); + try { + while (!this.stop) { + think(); + eat(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + log("stopped; eaten=" + this.eaten); + } + + private void think() throws InterruptedException { + Thread.sleep(this.random.nextInt(MAX_THINKING_DURATION_MS)); + } + + private void eat() throws InterruptedException { + log("try taking left"); + synchronized (this.left) { + log("left acquired"); + Thread.sleep(this.random.nextInt(MAX_TAKING_TIME_MS)); + log("try taking right"); + synchronized (this.right) { + log("right acquired"); + log("eating"); + this.eaten++; + Thread.sleep(this.random.nextInt(MAX_EATING_DURATION_MS)); + } + log("right released"); + } + log("left released"); + } +} diff --git a/src/pp.03.01-SynchPhilosopher/src/main/java/pp/PhilosopherExperiment.java b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/PhilosopherExperiment.java new file mode 100644 index 0000000..821fb07 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher/src/main/java/pp/PhilosopherExperiment.java @@ -0,0 +1,25 @@ +package pp; + +public class PhilosopherExperiment { + + static final int PHILOSOPHER_NUM = 5; + static final int EXP_DURATION_MS = 20000; + + public static void main(String... args) throws InterruptedException { + var chopsticks = new Chopstick[PHILOSOPHER_NUM]; + var philosophers = new Philosopher[PHILOSOPHER_NUM]; + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + chopsticks[i] = new Chopstick(); + } + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + philosophers[i] = new Philosopher(i, chopsticks[i], chopsticks[(i + 1) % PHILOSOPHER_NUM]); + } + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + philosophers[i].start(); + } + Thread.sleep(EXP_DURATION_MS); + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + philosophers[i].stopPhilosopher(); + } + } +} diff --git a/src/pp.03.01-SynchPhilosopher_solution/README.md b/src/pp.03.01-SynchPhilosopher_solution/README.md new file mode 100644 index 0000000..dc4f6d7 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "Dinnierende Philosoph:innen" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-01-SynchPhilosopher.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-dinierende-philosophinnen) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.01-SynchPhilosopher_solution/justfile b/src/pp.03.01-SynchPhilosopher_solution/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.01-SynchPhilosopher_solution/pom.xml b/src/pp.03.01-SynchPhilosopher_solution/pom.xml new file mode 100644 index 0000000..b4f0c16 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.01-SynchPhilosopher_solution + 1.0-SNAPSHOT + jar + + + pp.PhilosopherExperiment + 19 + 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.03.01-SynchPhilosopher_solution/src/main/java/pp/Chopstick.java b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/Chopstick.java new file mode 100644 index 0000000..1d14a3b --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/Chopstick.java @@ -0,0 +1,3 @@ +package pp; + +public class Chopstick {} diff --git a/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/Philosopher.java b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/Philosopher.java new file mode 100644 index 0000000..0dd1fdc --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/Philosopher.java @@ -0,0 +1,77 @@ +package pp; + +import java.util.Random; + +public class Philosopher extends Thread { + + static final int MAX_THINKING_DURATION_MS = 1000; + static final int MAX_EATING_DURATION_MS = 3000; + static final int MAX_TAKING_TIME_MS = 1000; + + private final Chopstick left; + private final Chopstick right; + private final Random random; + private int eaten; + private final int seat; + + private volatile boolean stop; + + private void log(String message) { + synchronized (Philosopher.class) { + for (var i = 1; i <= this.seat; i++) { + System.out.print(" "); + } + System.out.println(threadId() + " " + message); + } + } + + public void stopPhilosopher() { + log("stopping"); + this.stop = true; + interrupt(); + } + + public Philosopher(int seat, Chopstick left, Chopstick right) { + this.stop = false; + this.seat = seat; + this.left = left; + this.right = right; + this.random = new Random(); + this.eaten = 0; + } + + @Override + public void run() { + log("starting"); + try { + while (!this.stop) { + think(); + eat(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + log("stopped; eaten=" + this.eaten); + } + + private void think() throws InterruptedException { + Thread.sleep(this.random.nextInt(MAX_THINKING_DURATION_MS)); + } + + private void eat() throws InterruptedException { + log("try taking left"); + synchronized (this.left) { + log("left acquired"); + Thread.sleep(this.random.nextInt(MAX_TAKING_TIME_MS)); + log("try taking right"); + synchronized (this.right) { + log("right acquired"); + log("eating"); + this.eaten++; + Thread.sleep(this.random.nextInt(MAX_EATING_DURATION_MS)); + } + log("right released"); + } + log("left released"); + } +} diff --git a/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/PhilosopherExperiment.java b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/PhilosopherExperiment.java new file mode 100644 index 0000000..99e4757 --- /dev/null +++ b/src/pp.03.01-SynchPhilosopher_solution/src/main/java/pp/PhilosopherExperiment.java @@ -0,0 +1,32 @@ +package pp; + +public class PhilosopherExperiment { + + static final int PHILOSOPHER_NUM = 5; + static final int EXP_DURATION_MS = 20000; + + public static void main(String... args) throws InterruptedException { + var chopsticks = new Chopstick[PHILOSOPHER_NUM]; + var philosophers = new Philosopher[PHILOSOPHER_NUM]; + for (int i = 0; i < PHILOSOPHER_NUM; i++) { + chopsticks[i] = new Chopstick(); + } + // first n-1 philosophers + for (var i = 0; i < (PHILOSOPHER_NUM - 1); i++) { + philosophers[i] = new Philosopher(i, chopsticks[i], chopsticks[(i + 1)]); + } + // nth philosophers: initialize with right+left instead of left+right + philosophers[PHILOSOPHER_NUM - 1] = new Philosopher( + PHILOSOPHER_NUM - 1, + chopsticks[0], + chopsticks[PHILOSOPHER_NUM - 1] + ); + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + philosophers[i].start(); + } + Thread.sleep(EXP_DURATION_MS); + for (var i = 0; i < PHILOSOPHER_NUM; i++) { + philosophers[i].stopPhilosopher(); + } + } +} diff --git a/src/pp.03.02-BoundedQueueWaitNotify/README.md b/src/pp.03.02-BoundedQueueWaitNotify/README.md new file mode 100644 index 0000000..12cb5d9 --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "``wait``/``notifyAll`` für Ringpuffer" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-02-BoundedQueueWaitNotify.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-waitnotifyall-für-ringpuffer) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.02-BoundedQueueWaitNotify/justfile b/src/pp.03.02-BoundedQueueWaitNotify/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.02-BoundedQueueWaitNotify/pom.xml b/src/pp.03.02-BoundedQueueWaitNotify/pom.xml new file mode 100644 index 0000000..f20941f --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.02-BoundedQueueWaitNotify + 1.0-SNAPSHOT + jar + + + pp.BoundedBuffer + 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.03.02-BoundedQueueWaitNotify/src/main/java/pp/BoundedBuffer.java b/src/pp.03.02-BoundedQueueWaitNotify/src/main/java/pp/BoundedBuffer.java new file mode 100644 index 0000000..c00c1e5 --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify/src/main/java/pp/BoundedBuffer.java @@ -0,0 +1,82 @@ +package pp; + +public class BoundedBuffer { + + final Object[] items = new Object[8]; + int putptr, takeptr, count; + + public void put(T x) throws InterruptedException { + // solange der Speicher voll ist, warten + this.items[this.putptr] = x; + if (++this.putptr == this.items.length) { + this.putptr = 0; + } + ++this.count; + // nun ist etwas neues im Speicher: Alle wartenden Threads + // benachrichtigen + } + + public T take() throws InterruptedException { + // solange der Speicher leer ist, warten + @SuppressWarnings("unchecked") + var x = (T) this.items[this.takeptr]; + if (++this.takeptr == this.items.length) { + this.takeptr = 0; + } + --this.count; + // nun ist etwas Platz im Speicher: Alle wartenden Threads + // benachrichtigen + return x; + } + + public static void main(String... args) throws InterruptedException { + var mem = new BoundedBuffer(); + var p1 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + Thread.sleep(1000); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-1" + ); + var p2 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-2" + ); + var c1 = new Thread( + () -> { + try { + for (var j = 1; j <= 20; j++) { + System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take()); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Consumer-1" + ); + var now = System.currentTimeMillis(); + p1.start(); + p2.start(); + c1.start(); + p1.join(); + p2.join(); + c1.join(); + System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms"); + } +} diff --git a/src/pp.03.02-BoundedQueueWaitNotify_solution/README.md b/src/pp.03.02-BoundedQueueWaitNotify_solution/README.md new file mode 100644 index 0000000..12cb5d9 --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "``wait``/``notifyAll`` für Ringpuffer" +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-02-BoundedQueueWaitNotify.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-waitnotifyall-für-ringpuffer) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.02-BoundedQueueWaitNotify_solution/justfile b/src/pp.03.02-BoundedQueueWaitNotify_solution/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify_solution/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.02-BoundedQueueWaitNotify_solution/pom.xml b/src/pp.03.02-BoundedQueueWaitNotify_solution/pom.xml new file mode 100644 index 0000000..b4580bc --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify_solution/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.02-BoundedQueueWaitNotify_solution + 1.0-SNAPSHOT + jar + + + pp.BoundedBuffer + 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.03.02-BoundedQueueWaitNotify_solution/src/main/java/pp/BoundedBuffer.java b/src/pp.03.02-BoundedQueueWaitNotify_solution/src/main/java/pp/BoundedBuffer.java new file mode 100644 index 0000000..cf8570f --- /dev/null +++ b/src/pp.03.02-BoundedQueueWaitNotify_solution/src/main/java/pp/BoundedBuffer.java @@ -0,0 +1,84 @@ +package pp; + +public class BoundedBuffer { + + final Object[] items = new Object[8]; + int putptr, takeptr, count; + + public synchronized void put(T x) throws InterruptedException { + while (this.count == this.items.length) { + wait(); + } + this.items[this.putptr] = x; + if (++this.putptr == this.items.length) { + this.putptr = 0; + } + ++this.count; + notifyAll(); + } + + public synchronized T take() throws InterruptedException { + while (this.count == 0) { + wait(); + } + @SuppressWarnings("unchecked") + var x = (T) this.items[this.takeptr]; + if (++this.takeptr == this.items.length) { + this.takeptr = 0; + } + --this.count; + notifyAll(); + return x; + } + + public static void main(String... args) throws InterruptedException { + var mem = new BoundedBuffer(); + var p1 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + Thread.sleep(1000); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-1" + ); + var p2 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-2" + ); + var c1 = new Thread( + () -> { + try { + for (var j = 1; j <= 20; j++) { + System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take()); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Consumer-1" + ); + var now = System.currentTimeMillis(); + p1.start(); + p2.start(); + c1.start(); + p1.join(); + p2.join(); + c1.join(); + System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms"); + } +} diff --git a/src/pp.03.03-BoundedQueueAwaitSignal/README.md b/src/pp.03.03-BoundedQueueAwaitSignal/README.md new file mode 100644 index 0000000..dee18ac --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "``await``/``signal`` für Ringpuffer” +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-03-BoundedQueueAwaitSignal.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-awaitsignal-für-ringpuffer) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.03-BoundedQueueAwaitSignal/justfile b/src/pp.03.03-BoundedQueueAwaitSignal/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.03-BoundedQueueAwaitSignal/pom.xml b/src/pp.03.03-BoundedQueueAwaitSignal/pom.xml new file mode 100644 index 0000000..8030e3b --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.03-BoundedQueueAwaitSignal + 1.0-SNAPSHOT + jar + + + pp.BoundedBuffer + 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.03.03-BoundedQueueAwaitSignal/src/main/java/pp/BoundedBuffer.java b/src/pp.03.03-BoundedQueueAwaitSignal/src/main/java/pp/BoundedBuffer.java new file mode 100644 index 0000000..68bcf88 --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal/src/main/java/pp/BoundedBuffer.java @@ -0,0 +1,92 @@ +package pp; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class BoundedBuffer { + + final Lock lock = new ReentrantLock(); + final Condition notFull = this.lock.newCondition(); + final Condition notEmpty = this.lock.newCondition(); + + final Object[] items = new Object[8]; + int putptr, takeptr, count; + + public void put(T x) throws InterruptedException { + // solange der Speicher voll ist, warten + this.items[this.putptr] = x; + if (++this.putptr == this.items.length) { + this.putptr = 0; + } + ++this.count; + // nun ist etwas neues im Speicher: Alle wartenden Threads + // benachrichtigen + } + + public T take() throws InterruptedException { + // solange der Speicher leer ist, mit der Bedingungsvariablen notEmpty + // warten + @SuppressWarnings("unchecked") + var x = (T) this.items[this.takeptr]; + if (++this.takeptr == this.items.length) { + this.takeptr = 0; + } + --this.count; + // nun ist etwas Platz im Speicher: Alle für notFull wartenden Threads + // benachrichtigen + return x; + } + + public static void main(String... args) throws InterruptedException { + var mem = new BoundedBuffer(); + var p1 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + Thread.sleep(1000); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-1" + ); + var p2 = new Thread( + () -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println(Thread.currentThread().getName() + ": put=" + j); + Thread.sleep(1000); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Producer-2" + ); + var c1 = new Thread( + () -> { + try { + for (var j = 1; j <= 20; j++) { + System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take()); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, + "Consumer-1" + ); + var now = System.currentTimeMillis(); + p1.start(); + p2.start(); + c1.start(); + p1.join(); + p2.join(); + c1.join(); + System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms"); + } +} diff --git a/src/pp.03.03-BoundedQueueAwaitSignal_solution/README.md b/src/pp.03.03-BoundedQueueAwaitSignal_solution/README.md new file mode 100644 index 0000000..dee18ac --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal_solution/README.md @@ -0,0 +1,7 @@ +# Laboraufgabe "``await``/``signal`` für Ringpuffer” +- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-03-BoundedQueueAwaitSignal.html) +- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-awaitsignal-für-ringpuffer) + +# Materialien +- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html) +- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html) diff --git a/src/pp.03.03-BoundedQueueAwaitSignal_solution/justfile b/src/pp.03.03-BoundedQueueAwaitSignal_solution/justfile new file mode 100644 index 0000000..848084f --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal_solution/justfile @@ -0,0 +1,12 @@ +default: + mvn clean compile exec:java +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.03.03-BoundedQueueAwaitSignal_solution/pom.xml b/src/pp.03.03-BoundedQueueAwaitSignal_solution/pom.xml new file mode 100644 index 0000000..90093ec --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal_solution/pom.xml @@ -0,0 +1,61 @@ + + 4.0.0 + pp + pp.03.03-BoundedQueueAwaitSignal_solution + 1.0-SNAPSHOT + jar + + + pp.BoundedBuffer + 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.03.03-BoundedQueueAwaitSignal_solution/src/main/java/pp/BoundedBuffer.java b/src/pp.03.03-BoundedQueueAwaitSignal_solution/src/main/java/pp/BoundedBuffer.java new file mode 100644 index 0000000..4bd31a3 --- /dev/null +++ b/src/pp.03.03-BoundedQueueAwaitSignal_solution/src/main/java/pp/BoundedBuffer.java @@ -0,0 +1,96 @@ +package pp; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class BoundedBuffer { + final Lock lock = new ReentrantLock(); + final Condition notFull = this.lock.newCondition(); + final Condition notEmpty = this.lock.newCondition(); + + final Object[] items = new Object[8]; + int putptr, takeptr, count; + + public void put(T x) throws InterruptedException { + this.lock.lock(); + try { + while (this.count == this.items.length) { + this.notFull.await(); // unlock falls Bedingung + } + this.items[this.putptr] = x; + if (++this.putptr == this.items.length) { + this.putptr = 0; + } + ++this.count; + this.notEmpty.signal(); + } finally { + this.lock.unlock(); + } + } + + public T take() throws InterruptedException { + this.lock.lock(); + try { + while (this.count == 0) { + this.notEmpty.await(); + } + @SuppressWarnings("unchecked") + var x = (T) this.items[this.takeptr]; + if (++this.takeptr == this.items.length) { + this.takeptr = 0; + } + --this.count; + this.notFull.signal(); + return x; + } finally { + this.lock.unlock(); + } + } + + public static void main(String... args) throws InterruptedException { + var mem = new BoundedBuffer(); + var p1 = new Thread(() -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println( + Thread.currentThread().getName() + ": put=" + j); + Thread.sleep(1000); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, "Producer-1"); + var p2 = new Thread(() -> { + try { + for (var j = 1; j <= 10; j++) { + mem.put(j); + System.out.println( + Thread.currentThread().getName() + ": put=" + j); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, "Producer-2"); + var c1 = new Thread(() -> { + try { + for (var j = 1; j <= 20; j++) { + System.out.println(Thread.currentThread().getName() + + ": taken=" + mem.take()); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }, "Consumer-1"); + var now = System.currentTimeMillis(); + p1.start(); + p2.start(); + c1.start(); + p1.join(); + p2.join(); + c1.join(); + System.out.println( + "Runtime: " + (System.currentTimeMillis() - now) + "ms"); + } +}