zoukankan      html  css  js  c++  java
  • 进程同步——哲学家进餐问题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);
        }
    }
  • 相关阅读:
    软件构架 课堂练习一
    《软件构架实践》阅读笔记06
    《软件构架实践》阅读笔记05
    《软件构架实践》阅读笔记04
    接口如何实现多态
    c++虚函数的作用是什么?
    java中修饰符作用范围
    Servlet生命周期
    ERP理解
    内部类和匿名内部类
  • 原文地址:https://www.cnblogs.com/yfzhou/p/10341420.html
Copyright © 2011-2022 走看看