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 Philosopher left; private Philosopher 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 = (Philosopher) left; } @Override public void setRight(IPhilosopher right) { // TODO Auto-generated method stub // Cast auf Philosopher erforderlich this.right = (Philosopher) right; } @Override public void setSeat(int seat) { this.seat = seat; } @Override 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 (left.eating || 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; // } }