2015-05-26 2 views
-1

Я реализую проблемы столовых философов, и я сам столкнулся с проблемой, я не знаю, в чем причина, поэтому я здесь.

После обеда, когда я говорю им уйти, я хочу заставить их создавать отчеты, потому что это следующий этап их жизни. Когда я делаю так, все реагируют, но только один действует:Обеденные философы - я говорил всем, только один слушает

Консоль вывода:

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



DiningRoom класс:

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); } 
} 
+0

Вы проверили, в каком состоянии находятся каждый из философов, когда вы издали стоп? – RealSkeptic

+2

Ваш код довольно сложный и не компилируется. Если вы хотите, чтобы кто-то его проверил, я предлагаю сделать [MVCE] (http://stackoverflow.com/help/mcve): определить «вилку» и заменить материал журнала LogBook обычными printlns. Я подозрительный, проблема в том, что я сам записываю журнал. – markspace

+0

Я так не думаю. – Suspended

ответ

0

Я думаю, ваша проблема здесь в officiallyStartTheDinner:

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

Вы никогда не ждать ваших потоков до конца. Как только ваша основная программа выйдет, потоки умрут, потому что они не являются потоками демона. Возможно, вам лучше использовать ExecutorService для запуска runnables из пула потоков фиксированного размера. Затем вы можете shutdown() и awaitTermination(...), чтобы потоки могли выполнять свои задачи.

+0

Я даю вам «не», чтобы вставить нужное место. (Подсказка: до «die») – Ingo

+0

Вы правы, они работают как 5 секунд, а затем таймер просыпает спящего парня, который затем говорит каждому философу уйти. Благодарю. Я добавлю больше строк текста в код, возможно, это покажет проблему. – Suspended

2

Я взломал ваш код, чтобы он работал, а затем запускал отладчик. У вас две проблемы. Во-первых, вы фактически не реализуете алгоритм Dinning Philosopher. Вы просто пытаетесь взять блокировку (вилку) без каких-либо проверок или алгоритма выпуска. В моем отладчике по крайней мере два потока застряли в 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; }  
} 

Эти две переменные, leftInHand и rightInHand являются экземпляр переменных. Они только проверяют, есть ли у вас у вас есть замок. Они не проверяют, имеет ли другой философ замок.

Вторая проблема заключается в том, что у вас есть «while (true)» в середине цикла событий, предотвращая фактический выход любого потока.

+0

Я даже не пытался запустить его. Не заметил плохой логики блокировки. Отключенные потоки объяснят поведение. Хорошо поймал. – jgitter

+0

Спасибо за ваш комментарий, я узнал о вещах, которые я не знал, но я не удивлен, что мои философы застряли. Я целенаправленно не ссылался на какие-либо алгоритмы онлайн, и я ожидал, что код может не работать здесь и там. Просто из любопытства ... что вы имеете в виду, говоря, что мой код сложный? – Suspended

+0

Вы имеете в виду в моем комментарии после OP? Что код слишком сложный для отладки на глаз. – markspace