进程同步——哲学家进餐问题Java实现

哲学家就餐问题是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);
    }
}

 

转载于:https://www.cnblogs.com/yfzhou/p/10341420.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值