diff --git a/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java b/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java index edb96c8..c6418d3 100644 --- a/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java +++ b/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java @@ -18,6 +18,10 @@ public interface IPhilosopher { void stopPhilosopher(); + + + + default void log(int seat, String message) { synchronized (Philosopher.class) { for (var i = 1; i <= seat; i++) { diff --git a/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java b/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java index 8139cfb..636f3ad 100644 --- a/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java +++ b/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java @@ -1,20 +1,41 @@ package pp; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; +import static pp.PhilosopherExperiment.*; +import java.util.Random; + public class Philosopher extends Thread implements IPhilosopher { private int seat; + private Philosopher left; + private Philosopher right; + private Lock table; + private Condition canEat; + private volatile boolean eating = false; + private volatile boolean stopped = false; + private final Random random; + + public Philosopher() { + this.random = new Random(); + this.seat = 0; + this.stopped = false; + } @Override public void setLeft(IPhilosopher left) { // TODO Auto-generated method stub // Cast auf Philosopher erforderlich + if (left == null) throw new IllegalArgumentException("Left philosopher must not be null."); + this.left = (Philosopher) left; } @Override public void setRight(IPhilosopher right) { // TODO Auto-generated method stub // Cast auf Philosopher erforderlich + if (right == null) throw new IllegalArgumentException("Right philosopher must not be null."); + this.right = (Philosopher) right; } @Override @@ -26,11 +47,76 @@ public class Philosopher extends Thread implements IPhilosopher { public void setTable(Lock table) { // TODO Auto-generated method stub + this.table = table; + this.canEat = table.newCondition(); } @Override public void stopPhilosopher() { // TODO Auto-generated method stub + this.stopped = true; + this.interrupt(); + } + + public void run() { + try { + while (!stopped) { + think(); + beginEating(); + eat(); + endEating(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + + private void endEating() { + table.lock(); + try { + eating = false; + log(seat, "hat fertig gegessen"); + left.canEat.signal(); + right.canEat.signal(); + } finally { + table.unlock(); + } + } + + private void eat() throws InterruptedException { + Thread.sleep(random.nextInt(MAX_EATING_DURATION_MS)); + } + + + private void beginEating() throws InterruptedException { + table.lock(); + try { + while (left.eating || right.eating) { + log(seat, "wartet"); + canEat.await(); + } + eating = true; + log(seat, "isst jetzt"); + } finally { + table.unlock(); + } + } + + + + private void think() throws InterruptedException { + log(seat, "denkt"); + Thread.sleep(random.nextInt(MAX_THINKING_DURATION_MS)); + table.lock(); + try { + left.canEat.signal(); + right.canEat.signal(); + } finally { + table.unlock(); + } + } + }