哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题。
问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。
解决办法:
- 拿筷子之前判断两支筷子是否有人使用,都无人使用时才能拿起筷子。
- 不能独占一支筷子,造成死锁。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Philosopher implements Runnable { private static class Chopstick { private boolean[] chopsticks = {true, true, true, true, true}; public synchronized void take_two(int index) { while (!attempt(index)) { System.out.println(String.format("--哲学家%d--尝试拿筷子--失败...", index)); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(String.format("--哲学家%d--尝试拿筷子--成功...", index)); chopsticks[getLeft(index)] = false; chopsticks[getRight(index)] = false; } private boolean attempt(int index) { System.out.println(String.format("--哲学家%d--尝试拿筷子...", index)); return chopsticks[getLeft(index)] && chopsticks[getRight(index)]; } public synchronized void put_two(int index) { System.out.println(String.format("--哲学家%d--放下筷子...", index)); chopsticks[getLeft(index)] = true; chopsticks[getRight(index)] = true; notifyAll(); } int getLeft(int index) { return (index - 1 + chopsticks.length) % chopsticks.length; } int getRight(int index) { return index; } } private int index; private Chopstick chopsticks; public Philosopher(int index, Chopstick chopsticks) { this.index = index; this.chopsticks = chopsticks; } private void think() { System.out.println(String.format("--哲学家%d--正在思考...", index)); try { Thread.sleep(random(20 * 1000, 30 * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } private void eat() { System.out.println(String.format("--哲学家%d--正在吃饭...", index)); try { Thread.sleep(random(20 * 1000, 30 * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void run() { while (true) { think(); chopsticks.take_two(index); eat(); chopsticks.put_two(index); } } private static int random(int min, int max) { return min + (int) (Math.random() * (max - min + 1)); } public static void main(String[] args) { Chopstick chopsticks = new Chopstick(); Philosopher p1 = new Philosopher(0, chopsticks); Philosopher p2 = new Philosopher(1, chopsticks); Philosopher p3 = new Philosopher(2, chopsticks); Philosopher p4 = new Philosopher(3, chopsticks); Philosopher p5 = new Philosopher(4, chopsticks); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(p1); executorService.execute(p2); executorService.execute(p3); executorService.execute(p4); executorService.execute(p5); } }