什么是哲学家就餐问题?
我给出一种方法的实现
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();
}
}