0

我正在实施哲学家就餐问题,我自己也遇到了一个问题,我不知道是什么原因,所以我在这里。

晚饭后我告诉他们离开,我想强迫他们创建报告,因为那是他们生命的下一个阶段。当我这样做时,所有人都会回应,但只有一个行动:

控制台输出:

0 >> I was told to stop.
1 >> I was told to stop.
2 >> I was told to stop.
3 >> I was told to stop.
4 >> I was told to stop.
philosopher 0 reporting
report filed, total 1



这是哲学家类:

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

public class Philosopher implements Runnable {

    // 1 - eating
    // 2 - thinking
    // 3 - waiting
    // 4 - reporting
    private int id;
    private int state;
    private int eating;
    private int waiting;
    private int thinking;
    private int consecutiveWaitingTime;

    private long thinkingTime;
    private long initialDelay;
    private long eatingTime;
    private long waitingTime;

    private boolean thePartyIsOn;   
    private boolean leftInHand;
    private boolean rightInHand;
    private boolean speech = false;
    private boolean timeLineLogSent = false;

    private DiningRoom host;

    private Fork left;
    private Fork right; 

    private List<LogBookRecord> timelineLog;    

    public Philosopher(int idn, DiningRoom host){
        timelineLog = new ArrayList<LogBookRecord>();
        this.host = host;
        thePartyIsOn = true;
        leftInHand = false;
        rightInHand = false;                
        thinkingTime = 100l; //miliseconds
        eatingTime = 300l;
        waitingTime = 50l;
        initialDelay = idn*70; 
        consecutiveWaitingTime = 0;
        eating = 0;
        waiting = 0;
        thinking = 0;
        state = 3;      
        id = idn;       
    }   


    @Override
    public void run(){  
        if(speech){ System.out.println("philosopher " +id+ "!"); }
        while(thePartyIsOn){
            try { Thread.sleep(initialDelay); } 
            catch (InterruptedException e) { e.printStackTrace(); }
            log("Started dining with delay of " +initialDelay+ " miliseconds...");
            while(true){
                switch(state){
                case 1:  // eating
                    if(speech){ System.out.println("philosopher " +id+ " eating"); }
                    log("Eating...");
                    eating++;
                    try { Thread.sleep(eatingTime); } 
                    catch (InterruptedException e) { e.printStackTrace(); }
                    releaseForks(); 
                    state = 2;
                    break;
                case 2:  // thinking
                    if(speech){ System.out.println("philosopher " +id+ " thinking"); }
                    log("Thinking...");
                    thinking++;
                    try { Thread.sleep(thinkingTime);} 
                    catch (InterruptedException e1) { e1.printStackTrace(); }
                    state = 3;  
                    break;
                case 3: // waiting
                    if(speech){ System.out.println("philosopher " +id+ " waiting"); }
                    tryEating();
                    log("Waiting...");
                    waiting++;
                    if(consecutiveWaitingTime > 20 && !host.isStarvationAlertOn()){ 
                        host.pressStarvationAlertButton(id);                        
                    }
                    try { Thread.sleep(waitingTime); }
                    catch (InterruptedException e) { e.printStackTrace(); } 
                    break;
                case 4: // reporting
                    if(!timeLineLogSent){ 
                        System.out.println("philosopher " +id+ " reporting");
                        log("Creating final report...");
                        host.fileReport(id, timelineLog); 
                        timeLineLogSent = true;
                        thePartyIsOn = false;
                    }
                    break;              
                }
            }
        }
        if(speech){ System.out.println("PHILOSOPHER " +id+ ": My task is done. Good bye."); }
    }

    private void tryEating() {
        if(!leftInHand){ left.take(); leftInHand = true; }
        else if(!rightInHand){ right.take(); rightInHand = true;}
        else{ state = 1; }      
    }

    private void releaseForks() {       
        left.release();
        leftInHand = false;
        right.release();
        rightInHand = false;
    }

    private void log(String log){ timelineLog.add(new LogBookRecord(System.nanoTime(), ("PHILOSOPHER " +id+ ": " +log))); }

    public synchronized void reportTime(){ 
        System.out.println(id+ " >> I was told to stop.");
        log("I was told to stop!");
        log("eating: " +eating);
        log("waiting: " +waiting);
        log("thinking: " +thinking);
        state = 4; 
    }
    public void setLeftFork(Fork fl) {  left = fl; }
    public void setRightFork(Fork fr){ right = fr; }
}



餐厅等级:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import utilities.FileHandler;

public class DiningRoom {
    private String filename = "PhilosophersFeastReport.txt";    
    Philosopher[] guests;
    Fork[] forks;   
    private int guestsQty = 5;
    private int guestsLeftTheBuilding;
    public boolean starvationAlert;
    private List<LogBookRecord> diningRoomLog;
    private FileHandler fh;
    private int reportsFiled;   
    private long napTime;
    private boolean timeIsUp;
    Timer timer;
    int secondsLeft = 5;

    public DiningRoom(){
        timeIsUp = false;
        timer = new Timer();            
        napTime = 500l;
        m("Constructing the dining room...");               
        reportsFiled = 0;
        guestsLeftTheBuilding = 0;      
        diningRoomLog = new ArrayList<LogBookRecord>();

        m("Creating file for the report...");
        fh = new FileHandler();
        fh.createFile(filename);
        m("File [" +filename+ "] created...");

        starvationAlert = false;
        m("The guests are in...");
        guests = new Philosopher[guestsQty];
        forks = new Fork[guestsQty];

        m("Assigning forks...");
        prepareTheScene(guests,forks);

        m("Starting threads...");
        oficiallyStartTheDinner(guests);

        relax();
    }


    private void oficiallyStartTheDinner(Philosopher[] phs) {           
        timer.scheduleAtFixedRate(new TimerTask(){
            @Override
            public void run() {
                secondsLeft--;
                m(secondsLeft+ " seconds left..."); 
                if(secondsLeft <= 0){ 
                    timeIsUp = true;
                    this.cancel(); 
                    }
            }           
        }, 1000, 1000);     

        for(Philosopher p : phs){
            Thread t = new Thread(p);
            t.start();
        }
    }


    private void prepareTheScene(Philosopher[] table, Fork[] cutlery){
        m("Preparing the scene...");

        Fork f0 = new Fork();
        Philosopher ph0 = new Philosopher(0,this);      
        Fork f1 = new Fork();
        Philosopher ph1 = new Philosopher(1,this);
        Fork f2 = new Fork();
        Philosopher ph2 = new Philosopher(2,this);
        Fork f3 = new Fork();
        Philosopher ph3 = new Philosopher(3,this);
        Fork f4 = new Fork();
        Philosopher ph4 = new Philosopher(4,this);

        ph0.setRightFork(f0);
        ph0.setLeftFork(f1);        
        ph1.setRightFork(f1);
        ph1.setLeftFork(f2);        
        ph2.setRightFork(f2);
        ph2.setLeftFork(f3);        
        ph3.setRightFork(f3);
        ph3.setLeftFork(f4);        
        ph4.setRightFork(f4);
        ph4.setLeftFork(f0);    

        table[0] = ph0;
        table[1] = ph1;
        table[2] = ph2;
        table[3] = ph3;
        table[4] = ph4;

        cutlery[0] = f0;
        cutlery[1] = f1;
        cutlery[2] = f2;
        cutlery[3] = f3;
        cutlery[4] = f4;
    }


    private void relax(){
        boolean j = true;
        boolean k = true;
        while(reportsFiled != 5 && guestsLeftTheBuilding != 5){  // to be changed for correct conditions
            if(!timeIsUp){
                try {
                    Thread.sleep(napTime);
                    m("ZzZzZzZz...");
                }catch (InterruptedException e) {               
                    e.printStackTrace();
                }           
                if(j){ m("\tManagement is relaxing now..."); j = false; }   
                if(timeIsUp){               
                    if(k){ tellTheGuestsItIsTimeToGo(); k = false;}
                //break; 
                }
            }
        }


        m("Sorting the report log");
        Collections.sort(diningRoomLog);
        List<String> readyList = prepareTheList(diningRoomLog); 

        m("Calling file parser...");
        fh.writeToFile(filename, readyList);
        m("All done");
    }

    private List<String> prepareTheList(List<LogBookRecord> log) {
        m("Converting the log for file parser...");
        List<String> l = new ArrayList<String>();
        for(LogBookRecord lbr : log){
            l.add(lbr.toString());
        }
        return l;
    }

    private void tellTheGuestsItIsTimeToGo() {
        for(Philosopher p : guests){
            p.reportTime();
        }
    }       

    public static void main(String[] args){
        new DiningRoom();
    }

    public synchronized void fileReport(int philosopherId, List<LogBookRecord> report){
        diningRoomLog.add(new LogBookRecord(System.nanoTime(), "DINING ROOM: PHILOSOPHER " +philosopherId+ " filed a report"));
        diningRoomLog.addAll(report);
        reportsFiled++;
        m("report filed, total " +reportsFiled);
    }

    public synchronized void philosopherLeaving(int philosopherId){
        diningRoomLog.add(new LogBookRecord(System.nanoTime(), "PHILOSOPHER " +philosopherId+ " just left."));
    }
    public synchronized boolean isStarvationAlertOn(){ return starvationAlert; }

    public synchronized void pressStarvationAlertButton(int starvingPhilosopherId){
        diningRoomLog.add(new LogBookRecord(System.nanoTime(), "**** Philosopher "+starvingPhilosopherId+ " raised starvation alert!"));
        tellTheGuestsItIsTimeToGo();
        m("Philosopher " +starvingPhilosopherId+ " flipped starvation alert...");
    }   

    private void m(String s){ System.out.println(s); }
}
4

2 回答 2

2

我破解了你的代码,让它运行,然后在上面运行一个调试器。你有两个问题。首先是您实际上并没有实现餐饮哲学家的算法。您只是尝试在没有任何检查或释放算法的情况下获取锁(Fork)。在我的调试器中,至少有两个线程被卡住tryEating(),两个线程都被卡在等待永远不会释放的锁。

// broken: no checks before taking lock
private void tryEating() {
    if(!leftInHand){ left.take(); leftInHand = true; }
    else if(!rightInHand){ right.take(); rightInHand = true;}
    else{ state = 1; }      
}

这两个变量,leftInHandrightInHand实例变量。他们只检查你是否锁。他们不检查其他哲学家是否有锁。

第二个问题是您的事件循环中间有一个“while(true)”,从而阻止了任何线程实际退出。

    while(thePartyIsOn){
        try { Thread.sleep(initialDelay); } 
        catch (InterruptedException e) { e.printStackTrace(); }
        log("Started dining with delay of " +initialDelay+ " miliseconds...");
        while(true){         // <<-- oops
            switch(state){
于 2015-05-26T20:56:33.133 回答
0

我认为您的问题在正式开始TheDinner 中:

for(Philosopher p : phs){
    Thread t = new Thread(p);
    t.start();
}

你永远不会等待你的线程完成。一旦你的主程序退出,线程就会死掉,因为它们不是守护线程。您最好使用 ExecutorService 从固定大小的线程池中执行可运行对象。然后你可以shutdown()awaitTermination(...)允许线程完成它们的任务。

于 2015-05-26T20:44:44.760 回答