Test-SJ
Shahnam Javidnia 2025-05-01 15:54:08 +02:00
parent 0fc6dd421f
commit 7723b7fb35
2 changed files with 104 additions and 0 deletions

View File

@ -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++) {

View File

@ -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;
}
}