Я искал решение проблемы столовой философии в Википедии.
Решение по иерархии ресурсов
Я понимаю, как это работает и как нарушение круговой структуры предотвращает тупики, но как решение предотвращает голодание? Не может ли один или несколько потоков продолжаться, пока некоторые не добьются прогресса?
Если нет, что мешает этому произойти?
Реализация:
public class DinningphilMain {
public static void main(String[] args) throws InterruptedException {
int numPhil = 3;
Philosopher[] phil = new Philosopher[numPhil];
Fork[] forkArr=new Fork[numPhil];
for (int i = 0; i < numPhil; i ++) {
forkArr[i]= new Fork(i);
}
for (int i = 0; i < numPhil-1; i++) {
phil[i]=new Philosopher(i, forkArr[i], forkArr[i+1]);
}
phil[numPhil-1]= new Philosopher(numPhil-1, forkArr[0], forkArr[numPhil-1]);
for (Philosopher p : phil)
new Thread(p).start();
}
}
Это философский класс
import java.util.Random;
public class Philosopher implements Runnable {
int sleep = 1000;
int id;
int eatTime= 500;
Random rand = new Random();
Fork left;
Fork right;
public Philosopher(int id, Fork left, Fork right) {
this.id = id;
this.left = left;
this.right = right;
}
private void think() {
System.out.println("Philosopher " + id + " is thinking");
try {
int thinkingTime = rand.nextInt(sleep);
Thread.sleep(thinkingTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void getForks() {
System.out.println("Philosopher " + id + " is picking up forks");
try {
left.get();
right.get();
System.out.println("Philosopher " + id + " has both forks");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void releaseForks() {
System.out.println("Philosopher " + id + " is putting down forks");
left.release();
right.release();
}
private void eat() {
System.out.println("Philosopher " + id + " is eating");
try {
Thread.sleep(eatTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
getForks();
eat();
releaseForks();
think();
}
}
}
Это вилка класса
public class Fork {
private int id;
private Thread thread;
public Fork(int id) {
this.id = id;
thread = null;
}
public int getId() {
return id;
}
public synchronized void get() throws InterruptedException {
if (thread != null)
this.wait();
thread = Thread.currentThread();
}
public synchronized void release() {
if (thread == Thread.currentThread())
thread = null;
this.notify();
}
}