• JAVA多线程学习--哲学家就餐问题


    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题。

    问题描述:一圆桌前坐着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结果,因为每个时刻最多能够满足两个人同时进餐,且两人座位不相邻。

       

  • 相关阅读:
    Java零基础学习(四)JSP与Servlet
    Java零基础学习(三)封装继承多态
    vsftpd+nginx搭建图片服务器的一些问题
    1003. 我要通过!(20)(两种语言的运行时间差异)
    acm 1108 java做法
    acm 2020 用java实现
    acm 2519 java做法
    acm 2040 java做法
    acm 2003 java做法
    acm 2041 java的做法
  • 原文地址:https://www.cnblogs.com/vettel/p/3438257.html
Copyright © 2020-2023  润新知