• Java多线程,哲学家就餐问题


    问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。

    解决办法:

    1、添加一个服务生,只有当经过服务生同意之后才能拿筷子,服务生负责避免死锁发生。

    2、每个哲学家必须确定自己左右手的筷子都可用的时候,才能同时拿起两只筷子进餐,吃完之后同时放下两只筷子。

    3、规定每个哲学家拿筷子时必须拿序号小的那只,这样最后一位未拿到筷子的哲学家只剩下序号大的那只筷子,不能拿起,剩下的这只筷子就可以被其他哲学家使用,避免了死锁。这种情况不能很好的利用资源。 

    代码实现:实现第2种方案

    代码如下:
    package cn.edu.sdust.Philosopher;


    /*每个哲学家相当于一个线程*/
    class Philosopher extends Thread{
        private String name;
        private Fork fork;
        public Philosopher(String name,Fork fork){
            super(name);
            this.name=name;
            this.fork=fork;
        }

        public void run(){
            while(true){
                thinking();
                fork.takeFork();
                eating();
                fork.putFork();
            }

        }

       
        public void eating(){
            System.out.println("I am Eating:"+name);
            try {
                sleep(1000);//模拟吃饭,占用一段时间资源
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

       
        public void thinking(){
            System.out.println("I am Thinking:"+name);
            try {
                sleep(1000);//模拟思考
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    class Fork{
        /*5只筷子,初始为都未被用*/
        private boolean[] used={false,false,false,false,false,false};

        /*只有当左右手的筷子都未被使用时,才允许获取筷子,且必须同时获取左右手筷子*/
        public synchronized void takeFork(){
            String name = Thread.currentThread().getName();
            int i = Integer.parseInt(name);
            while(used[i]||used[(i+1)%5]){
                try {
                    wait();//如果左右手有一只正被使用,等待
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            used[i ]= true;
            used[(i+1)%5]=true;
        }

        /*必须同时释放左右手的筷子*/
        public synchronized void putFork(){
            String name = Thread.currentThread().getName();
            int i = Integer.parseInt(name);

            used[i ]= false;
            used[(i+1)%5]=false;
            notifyAll();//唤醒其他线程
        }
    }

    //测试
    public class ThreadTest {

        public static void main(String []args){
            Fork fork = new Fork();
            new Philosopher("0",fork).start();
            new Philosopher("1",fork).start();
            new Philosopher("2",fork).start();
            new Philosopher("3",fork).start();
            new Philosopher("4",fork).start();
        }
    }

    运行结果:

    代码如下:
    I am Thinking:0
    I am Thinking:2
    I am Thinking:3
    I am Thinking:1
    I am Thinking:4
    I am Eating:0
    I am Eating:2
    I am Thinking:0
    I am Eating:4
    I am Thinking:2
    I am Eating:1
    I am Thinking:4
    I am Eating:3
    I am Thinking:1
    I am Eating:0
    I am Thinking:3
    I am Eating:2
    I am Thinking:0
    I am Eating:4
    I am Thinking:2

    分析:上述解决方案解决了死锁问题。可以看到最多只能有两条相邻的eating结果,因为每个时刻最多能够满足两个人同时进餐,且两人座位不相邻。

  • 相关阅读:
    Spring Boot Docker
    基于 Spring Security 的前后端分离的权限控制系统
    Java图片加水印
    Linux安装Nexus
    Spring Security 入门篇
    树形结构的菜单表设计与查询
    延迟队列的常用的实现方式
    Spring Boot 自动配置 源码分析
    Spring Boot 启动过程
    服务端如何防止重复支付
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3706145.html
Copyright © 2020-2023  润新知