哲学家就餐问题作为多线程经典问题中其中一个,解决方案有多种。其中下面介绍的方案是:哲学家轮番判断左右手的筷子是否处于可用状态,如果两边都可用,则拿起筷子;其中任意一边不可用,则阻塞哲学家线程。
public class Philosopher implements Runnable{
private Fork fork;
private String name;
public Philosopher(String name,Fork fork){
this.name = name;
this.fork = fork;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
thinking();
fork.takeFork(name);
eating();
fork.putDownFork(name);
}
}
private void thinking(){
try {
System.out.println("哲学家在思考");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void eating(){
try {
System.out.println("哲学家在吃饭");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Fork fork = new Fork();
Philosopher p1 = new Philosopher("0",fork);
Philosopher p2 = new Philosopher("1",fork);
Philosopher p3 = new Philosopher("2",fork);
Philosopher p4 = new Philosopher("3",fork);
Philosopher p5 = new Philosopher("4",fork);
new Thread(p1).start();
new Thread(p2).start();
new Thread(p3).start();
new Thread(p4).start();
new Thread(p5).start();
}
}
class Fork{
private boolean[] isUsed = {false,false,false,false,false};
public synchronized void takeFork(String name){
int i = Integer.valueOf(name);
while(isUsed[i]||isUsed[(i+1)%5]){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notifyAll();
System.out.println("哲学家"+name+":拿起了筷子"+i+"和"+(i+1)%5);
isUsed[i]=isUsed[(i+1)%5]=true;
}
public synchronized void putDownFork(String name){
int i = Integer.valueOf(name);
System.out.println("哲学家"+name+":放下了筷子"+i+"和"+(i+1)%5);
isUsed[i]=isUsed[(i+1)%5]=false;
notifyAll();
}
}