From 7723b7fb35df69f689bc2dd1bde292f9b1ff205e Mon Sep 17 00:00:00 2001 From: Shahnam Javidnia <3015418@stud.hs-mannheim.de> Date: Thu, 1 May 2025 15:54:08 +0200 Subject: [PATCH] V1.0 --- .../src/main/java/pp/IPhilosopher.java | 5 + .../src/main/java/pp/Philosopher.java | 99 +++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java b/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java index edb96c8..d683c1f 100644 --- a/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java +++ b/pp.A1-CondPhilosophers/src/main/java/pp/IPhilosopher.java @@ -18,6 +18,11 @@ public interface IPhilosopher { void stopPhilosopher(); + void signal(); + + boolean isEating(); + + 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 7005aaa..8c400c7 100644 --- a/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java +++ b/pp.A1-CondPhilosophers/src/main/java/pp/Philosopher.java @@ -1,20 +1,32 @@ package pp; import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; +import static pp.PhilosopherExperiment.*; + public class Philosopher extends Thread implements IPhilosopher { private int seat; + private IPhilosopher left; + private IPhilosopher right; + private Lock table; + private Condition canEat; + private boolean eating = false; + private boolean stopped = false; @Override public void setLeft(IPhilosopher left) { // TODO Auto-generated method stub // Cast auf Philosopher erforderlich + this.left = left; } @Override public void setRight(IPhilosopher right) { // TODO Auto-generated method stub // Cast auf Philosopher erforderlich + + this.right = right; } @Override @@ -26,11 +38,98 @@ 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(); + } + + // Hauptlogik des Philosophen: Der Philosoph denkt, versucht zu essen, isst und beendet das Essen. + public void run() { + try { + while (!stopped) { + think(); // denkt eine Weile + beginEating(); // wartet, falls nötig, bis beide Nachbarn nicht essen + eat(); // isst eine zufällige Zeit + endEating(); // beendet das Essen und signalisiert Nachbarn + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + // Diese Methode wird aufgerufen, wenn der Philosoph mit dem Essen fertig ist. + // Sie setzt seinen Status zurück und signalisiert den Nachbarn, dass sie es nun versuchen können. + private void endEating() { + table.lock(); + try { + eating = false; + log(seat, "hat fertig gegessen"); + left.signal(); + right.signal(); + } finally { + table.unlock(); + } + } + + // Diese Methode simuliert das tatsächliche Essen mit einer zufälligen Dauer. + private void eat() throws InterruptedException { + Thread.sleep((long) (Math.random() * MAX_EATING_DURATION_MS)); + } + + // Diese Methode prüft, ob einer der Nachbarn gerade isst. + // Wenn ja, wartet dieser Philosoph auf seine Bedingung. + // Wenn beide frei sind, beginnt er zu essen. + private void beginEating() throws InterruptedException { + table.lock(); + try { + while (((Philosopher) left).eating || ((Philosopher) right).eating) { + log(seat, "wartet"); + canEat.await(); // wartet, bis signal() von einem anderen Philosophen aufgerufen wird + } + eating = true; + log(seat, "isst jetzt"); + } finally { + table.unlock(); + } + } + + + // Der Philosoph denkt für eine gewisse Zeit (zufällig), danach signalisiert er den Nachbarn, + // dass er nun fertig ist mit Denken, was eventuell anderen hilft zu essen. + private void think() throws InterruptedException { + log(seat, "denkt"); + Thread.sleep((long) (Math.random() * MAX_THINKING_DURATION_MS)); + table.lock(); + try { + left.signal(); + right.signal(); + } finally { + table.unlock(); + } + } + + // Diese Methode wird von anderen Philosophen aufgerufen, + // um diesen Philosophen zu wecken (z.B nach Ende einer Essensphase). + public void signal() { + table.lock(); + try { + canEat.signal(); + } finally { + table.unlock(); + } + } + + // Gibt zurück, ob dieser Philosoph aktuell isst – wichtig für die Nachbarn. + public boolean isEating() { + return eating; + } + }