Java实现哲学家就餐问题

什么是哲学家就餐问题?

  • 可以参考百度百科
  • 或者维基百科维基百科

我给出一种方法的实现

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 philosopherList;  //store philosophers

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

    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();
    }
}

你可能感兴趣的:(Java)