假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。即使没有死锁,也有可能发生资源耗尽。
/** * 筷子 */ public class Chopstick { private boolean taken=false; public synchronized void take() throws InterruptedException{ while (taken){ wait(); } taken=true; } public synchronized void drop(){ taken=false; notifyAll(); } }
/** * 哲学家 */ public class Philosopher implements Runnable{ private Chopstick left; private Chopstick right; private final int id; private final int ponderFactor; private Random rand=new Random(47); private void pause() throws InterruptedException{ if(ponderFactor==0) return; TimeUnit.MILLISECONDS.sleep(rand.nextInt(ponderFactor*250)); } public Philosopher(Chopstick left,Chopstick right,int ident ,int ponder){ this.left=left; this.right=right; id=ident; ponderFactor=ponder; } @Override public void run() { try { while(!Thread.interrupted()){ System.out.println(this+" "+" thinking"); pause(); System.out.println(this+" "+"grabbing right"); right.take(); System.out.println(this+" "+" grabbing left"); left.take(); System.out.println(this+" eating"); pause(); right.drop(); left.drop(); } } catch (InterruptedException e) { System.out.println(this+" exiting via interrupt"); } } public String toString(){ return "Philosopher "+id; } }
public class DeadlockingDiningPhilosophers { public static void main(String[] args)throws Exception{ int ponder=0; int size=5; ExecutorService exec= Executors.newCachedThreadPool(); Chopstick[] sticks=new Chopstick[size]; for(int i=0;i<size;i++) sticks[i]=new Chopstick(); for(int i=0;i<size;i++) exec.execute(new Philosopher(sticks[i],sticks[(i+1)%size],i,ponder)); System.out.println("Press 'Enter' to quit"); System.in.read(); exec.shutdownNow(); } }