Java实现哲学家就餐问题

原创 2015年11月19日 21:03:57

什么是哲学家就餐问题?

我给出一种方法的实现

Chandy/Misra解法

1984年,K. Mani Chandy和J. Misra提出了哲学家就餐问题的另一个解法,允许任意的用户(编号P1, …,
Pn)争用任意数量的资源。与资源分级解法不同的是,这里编号可以是任意的。

  • 把筷子凑成对,让要吃的人先吃,没筷子的人得到一张换筷子券。
  • 饿了,把换筷子券交给有筷子的人,有筷子的人吃饱了会把筷子交给给券的人。有了券的人不会再得到第二张券。 保证有筷子的都有得吃。
  • 这个解法允许很大的并行性,适用于任意大的问题。

Java代码

  • Util.java
package com.coderbean.test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Chang on 15/11/19.
 */
public class Util {
    int num = 0;
    List<Philosopher> philosopherList;  //store philosophers

    public Util() {
        philosopherList = new ArrayList<>();
//        philosopherList = new ArrayList<Philosopher>();
    }

    public Util(int num) {
        this();
        this.num = num;
    }

    public synchronized boolean getForks() {
        if(num>2) {
            num -= 2;
            return true;
        } else {
            return false;
        }
    }

    public synchronized void findBoss(Philosopher phi) {
        for(Philosopher p:philosopherList) {
            if(phi==p)
                continue;
            if(p.hasForks()&&!p.hasTicket()) {
                p.setPhilosopher(phi);
                p.setHasTicket(true);
                System.out.println(phi.getName()+"'s Boss is " +p.getName());
                phi.setHasTicket(false);
                System.out.println(""+phi.hasForks()+"餐具-"+phi.getName());
                phi.setHasForks(false);
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public synchronized void freeForks(Philosopher philosopher) {
        philosopher.getPhilosopher().setHasForks(true);
        System.out.println(""+philosopher.getName()+"给了"+philosopher.getPhilosopher().getName()+"餐具");
        philosopher.setHasForks(false);
        notifyAll();
    }
    public synchronized void debug() {
        System.out.println("\n" + philosopherList.size());
        for (Philosopher p : philosopherList) {
            System.out.println(p.hasForks() + "-" + p.hasTicket() + "\n");
        }
    }
}
  • Philosopher.java
package com.coderbean.test;

/**
 * Created by Chang on 15/11/19.
 */
public class Philosopher implements Runnable {
    private Util util;
    private String name;
    private boolean hasTicket;
    private boolean hasForks;
    private Philosopher philosopher;


    public Philosopher() {
        name = null;
        util = new Util();
        hasTicket = false;
        hasForks = false;
    }

    public Philosopher getPhilosopher() {
        return philosopher;
    }

    public String getName() {
        return name;
    }

    public void setPhilosopher(Philosopher philosopher) {
        this.philosopher = philosopher;
    }

    public boolean hasTicket() {
        return hasTicket;
    }

    public void setHasForks(boolean hasForks) {
        this.hasForks = hasForks;
    }

    public boolean hasForks() {
        return hasForks;
    }

    public void setHasTicket(boolean hasTicket) {
        this.hasTicket = hasTicket;
    }

    /**
     * 构造方法
     * @param util 筷子管理程序
     * @param name 哲学家名字
     */
    public Philosopher(Util util, String name) {
        this();
        this.util = util;
        this.name = name;
    }



    public void think(){
        System.out.println("I am Thinking----"+this.name);
        try {
            Thread.sleep(1000);  //模拟思考耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void eat() {
        System.out.println("----------------------------I am Eating--"+this.name);
        try {
            Thread.sleep(500); //模拟吃饭耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void run() {
        philosopher = new Philosopher();
        this.util.philosopherList.add(this); //take self to the list in Util
        this.hasForks = util.getForks();
        this.hasTicket = !this.hasForks;

        while (true) {
            this.think();

            if (this.hasForks) { // if has forks ,eat
                eat();
                if (this.hasTicket) { //有票有筷子 if has ticket, give forks to the ticket owner
                    util.freeForks(this);
                }//有筷子没票 什么都不干

            } else if (this.hasTicket) { //有票没筷子,找有筷子的人,给他票
                util.findBoss(this);
            }// 没筷子没票,什么都不敢
//            util.debug();
        }
    }
}
  • Main.java
package com.coderbean.test;

/**
 * Created by Chang on 15/11/19.
 */
public class Main {
    public static void main(String[] args) {
        Util util = new Util(5);
        new Thread(new Philosopher(util,"1")).start();
        new Thread(new Philosopher(util,"2")).start();
        new Thread(new Philosopher(util,"3")).start();
        new Thread(new Philosopher(util,"4")).start();
        new Thread(new Philosopher(util,"5")).start();
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

哲学家就餐问题的分析与解决方案

1.进程互斥与同步,死锁基本知识在多道程序环境下,进程有异步和同步两种并发执行方式。异步执行是指运行中的各进程在操作系统的调度下以不可预知的速度向前推进。异步执行的进程大多没有时序要求,不存在“执行结...

哲学家进餐问题

 哲学家进餐问题: (一)问题: 5个哲学家围坐在一个圆桌上,每两个哲学家之间都有一只筷子,哲学家平时进行思考,只有当他们饥饿时,才拿起筷子吃饭。 规定每个哲学家只能先取其左边筷子,然后取...

java多线程--哲学家就餐问题

java死锁,哲学家就餐问题

java 多线程 死锁 哲学家就餐问题

现在你理解了,一个对象可以有synchronized方法或其他形式的加锁机制来防止别的任务在互斥还没有释放的时候就访问这个对象。你已经学习过,任务可以变成阻塞状态,所以就可能出现两种情况:某个惹我怒在...

尝试解决哲学家进餐问题(Java实现)

一. 问题描述 5个哲学家,5跟筷子,哲学家必须用两只筷子吃东西。他们只能使用自己左右手边的那两只筷子。做到不产生死锁以及要求高并发性。 二.  资源加锁法 直接给所请求...

哲学家进餐问题与生产者与消费者问题(java实现)

import java.util.concurrent.Semaphore; public class Test2 { /** * 哲学家进餐问题 */ public static void...

java多线程哲学家思考吃饭问题

package test; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.ut...

Java面试题全集(上)

2013年年底的时候,我看到了网上流传的一个叫做《Java面试题大全》的东西,认真的阅读了以后发现里面的很多题目是重复且没有价值的题目,还有不少的参考答案也是错误的,于是我花了半个月时间对这个所谓的《...

Thinking in Java---从哲学家就餐问题看死锁现象

我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象。而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)