Chandy/Misra解法 解决哲学家就餐问题 java实现

Chandy/Misra解法[编辑]

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

  • 对每一对竞争一个资源的哲学家,新拿一个餐叉,给编号较低的哲学家。每只餐叉都是“干净的”或者“脏的”。最初,所有的餐叉都是脏的。
  • 当一位哲学家要使用资源(也就是要吃东西)时,他必须从与他竞争的邻居那里得到。对每只他当前没有的餐叉,他都发送一个请求。
  • 当拥有餐叉的哲学家收到请求时,如果餐叉是干净的,那么他继续留着,否则就擦干净并交出餐叉。
  • 当某个哲学家吃东西后,他的餐叉就变脏了。如果另一个哲学家之前请求过其中的餐叉,那他就擦干净并交出餐叉。
  • 这个解法允许很大的并行性,适用于任意大的问题。

下面是java 的实现


package Philosopher.ChandyMisra;

import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhensheng on 2016/10/18.
 */

class Stick {
    int owner;
    boolean dirty;
    int number;
    public synchronized void setStatus(boolean status){
        dirty = status;
    }
    public synchronized boolean getStatus(){
        return this.dirty;
    }
    public synchronized void setOwner(int owner){
        this.owner = owner;
    }
    public synchronized int getOwner(){
        return owner;
    }

    public Stick(boolean dirty, int number) {
        this.dirty = dirty;
        this.number = number;
    }
}

public class Philo implements Runnable {
    Stick leftStick, rightStick;
    Philo leftPhilo, rightPhilo;
    int number, eatTimes;
    //DinningPhi dinningExam;
    //Thread t;


    public Philo(int number, int eatTimes) {
        this.number = number;
        this.eatTimes = eatTimes;
    }

    public void eating(){
        try{
            Thread.sleep(3000);
        }catch(InterruptedException ie){
            System.out.println("Catch an Interrupted Exception!");
            return;
        }
        leftStick.setStatus(true);
        rightStick.setStatus(true);
        eatTimes++;
        System.out.println("Philo "+ number + "is eating " + ": "+ eatTimes );
        //dinningExam.repaint();
    }

    public boolean answer(Stick used){
        boolean retFlag = false;
        synchronized(this){
            if(used.getStatus()){
                if(used == leftStick)
                    used.setOwner(leftPhilo.number);
                else if(used == rightStick)
                    used.setOwner(rightPhilo.number);
                else{
                    System.out.println("Error status!");
                    retFlag = false;
                }
                used.setStatus(false);
                retFlag = true;
            }
            else
                retFlag = false;
        }
        if(retFlag)
            System.out.println("Philo "+ number + "request success!" );
            //dinningExam.repaint();
        return retFlag;
    }

    @Override
    public void run() {
        Random r = new Random();
        int intR;

        while(true){
            while(leftStick.getOwner() != number | rightStick.getOwner() != number){
                intR = r.nextInt();
                if(intR % 2 == 0 && leftStick.getOwner() != number)
                    leftPhilo.answer(leftStick);
                else if(intR % 2 == 1 && rightStick.getOwner() != number)
                    rightPhilo.answer(rightStick);
            }
            synchronized(this){
                if(leftStick.getOwner() == number
                        && rightStick.getOwner() == number){
                    eating();
                }
            }
            try{
                int sleepSec = r.nextInt();
                if(sleepSec < 0)
                    sleepSec = -sleepSec;
                Thread.sleep(sleepSec % 500);
            }catch(InterruptedException ie){
                System.out.println("Catch an Interrupted Exception!");
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        Philo[] ps = new Philo[5];
        Stick[] ss = new Stick[5];
        for (int i = 0; i < 5 ; i++) {
            ss[i] = new Stick(true, i);
            ps[i]= new Philo(i,0);
        }
        System.out.println((0-1)%5);
        for (int i = 0; i < 5; i++) {
            ps[i].leftPhilo= ps[(i+4)%5];
            ps[i].rightPhilo= ps[(i+1)%5];
            ps[i].leftStick = ss[i];
            ps[i].rightStick=ss[(i+1)%5];
        }
        for (int i = 0; i < 5; i++) {
            exec.execute(ps[i]);
        }
        exec.shutdown();

    }
}

output

Philo 2request success!
Philo 2request success!
Philo 3request success!
Philo 3request success!
Philo 0is eating : 1
Philo 0request success!
Philo 0request success!
Philo 1is eating : 1
Philo 4is eating : 1
Philo 1request success!
Philo 4request success!
Philo 1request success!
Philo 4request success!
Philo 3is eating : 1
Philo 0is eating : 2
Philo 3request success!
...

你可能感兴趣的:(java,多线程,并发)