哲学家进餐问题解决思路 JAVA实现

package com.test.server.current;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 哲学家进餐问题解决方案之回退法,即制定规则,哲学家总是要先拿起左手筷子再拿起右手筷子,
 * 当一个哲学家拿起左手筷子并且要求拿右手时,要求占用右手筷子的哲学家放弃筷子
 */
public class PhilosopherMeal {
    //筷子
    public static class Chopstick {
        private boolean canTake = true;
        //筷子编号
        private int id;
        private int status = -1;

        public Chopstick(int id) {
            this.id = id;
        }

        public boolean getStatus(int pid) {
            return status == pid;

        }

        /**
         * @param pid 拿筷子的哲学家
         */
        public void take(int pid) throws InterruptedException {
            synchronized (this) {
                while (!canTake) {
                    //保证哲学家能拿到右边筷子,防止死锁
                    if (pid == id - 1) {
                        drop(id);
                        break;
                    }
                    wait();
                }
                System.out.println(pid + " 拿到筷子 " + id);
                canTake = false;
                status = pid;
            }
        }

        /**
         * @param pid 拿、放筷子的哲学家
         */
        public void drop(int pid) {
            synchronized (this) {
                if (status == pid) {
                    System.out.println(pid + " 放下筷子 " + id);
                    canTake = true;
                    status = -1;
                    this.notifyAll();
                }
            }
        }
    }

    //z
    public static class Philosopher implements Runnable {
        private Chopstick left;
        private Chopstick right;
        private int id;

        Philosopher(int id, Chopstick left, Chopstick right) {
            this.id = id;
            this.left = left;
            this.right = right;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    //哲学家总是先拿左手边再拿右手边,
                    left.take(id);
                    right.take(id);
                    //检查一下左手筷子有没有被 拿走
                    synchronized (left) {
                        if (left.getStatus(id)) {
                            System.out.println(id + " 开始进餐");
                            Thread.sleep(1000);
                            System.out.println(id + " 进餐完毕");
                        } else {
                            left.wait();
                        }
                    }
                    left.drop(id);
                    right.drop(id);
                    System.out.println(id + " 正在思考");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        int size = 5;
        Chopstick[] chopsticks = new Chopstick[size];
        for (int i = 0; i < size; i++) {
            Chopstick chopstick = new Chopstick(i);
            chopsticks[i] = chopstick;
        }
        ExecutorService pool = new ThreadPoolExecutor(5, 5, 5L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
        for (int i = 0; i < size; i++) {

            pool.execute(new Philosopher(i, chopsticks[i], chopsticks[(i + 1) % size]));
        }


    }
}

 

上一篇:操作系统中经典的死锁的问题


下一篇:VUE关于data对象中数组修改和对象添加属性的响应式问题