2015-04-22 7 views
0

Надеюсь, это не повторный вопрос, но я рассмотрел все ответы в других вопросах, и никто не удовлетворил мою проблему.Темы не работают одновременно

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

Philosopher 1 is EATING. 
Philosopher 1 is THINKING. 
Philosopher 5 is EATING. 
Philosopher 5 is THINKING. 
Philosopher 3 is EATING. 
Philosopher 3 is THINKING. 

... и так далее. Ожидаемый результат не имеет порядка. Потоки должны выполняться одновременно. Вот мой код, все это здесь, с интерфейсом, просто определяющим размер DINERS (5) и штата. _______ является перечислением с тремя состояниями: State.HUNGRY, State.THINKING и State.EATING.

import java.lang.Runnable;              
import java.util.concurrent.locks.*;            
import java.util.Random;               
import java.lang.Thread;               
import java.util.concurrent.TimeUnit;           
/**                    
* This class handles the Philosophers, I hope they are hungry.     
*          
* @version 4-20-15                
*/                    
public class Diner implements Runnable, PhilosopherInterface {     

/** The lock used to control Thread access */        
private final ReentrantLock lock;           
/** The state that the Philosopher is in (ex: Eating, Thinking etc.) */  
private State current;              
/** The random number used to generate time sleeping */      
private Random timeGenerator;            
/** The maximum time a thread can sleep */         
private final int maxTimeToSleep = 5000;          
/** The minimum time a thread can sleep (1ms) */        
private final int minTimeToSleep = 1;          
private int philNum;               
private int philIndex;              
private Condition[] condition;            
private State[] states;              

public Diner(ReentrantLock lock, int philNumber, Condition[] condition, State[] states) 

    philNum = philNumber;             
    philIndex = philNum - 1;             
    current = states[philNumber-1];           
    timeGenerator = new Random();           
    this.lock = lock;              
    this.condition = condition;            
    this.condition[philIndex] = lock.newCondition();       
    this.states = states;             
    states[philIndex] = State.THINKING;          


}                   

@Override                 
public void takeChopsticks() {            

    states[philIndex] = State.HUNGRY;          
    lock.lock();                
    try{                  
     int left = philIndex-1;            
     int right = philIndex+1;            
     if(philNum == DINERS) right = 0;          
     if(philNum == 1) left = DINERS - 1; 
test(left, philIndex, right);          
     if(states[philIndex] != State.EATING) {        
      condition[philIndex].await();         
     }                 
    }catch(InterruptedException e){}           

}                   

@Override                 
public void replaceChopsticks() {           
    try{                  
    states[philIndex] = State.THINKING;          
    int left = philIndex-1;             
    int right = philIndex+1;             
    if(philNum == DINERS) right = 0;           
    if(philNum == 1) left = DINERS - 1;          
    int leftOfLeft = left-1;             
    int rightOfRight = right+1;            
    if(left == 0) leftOfLeft = DINERS-1;          
    test(leftOfLeft, left, philIndex);          
    if(right == DINERS-1) rightOfRight = 0;         
    test(philIndex, right, rightOfRight);         
    }finally{ lock.unlock(); }            
    //states[philIndex] = State.THINKING;         
    //condition[left].signal();            
    //condition[right].signal();            
}                   



public void think() { 
System.out.println("Philosopher " + philNum + " is " + State.THINKING + "."); 
    int timeToSleep = timeGenerator.nextInt(maxTimeToSleep) + minTimeToSleep; 
    try {                 
     Thread.sleep(500);             
    }catch(InterruptedException e) {}          
}                   

public void eat() {               

     System.out.println("Philosopher " + philNum + " is " + State.EATING + "."); 
    int timeToSleep = timeGenerator.nextInt(maxTimeToSleep) + minTimeToSleep; 
    try {                 
     Thread.sleep(500);             
    }catch(InterruptedException e){}           
}                   

@Override                 
public void run() {               

    while(true) {               

     think();                
     takeChopsticks();             
     eat();                
     replaceChopsticks();             
    }                  
}                   

public State getState() {             
    return current;               
}                   

private void test(int left, int current, int right) {      
    if(states[left] != State.EATING && states[current] == State.HUNGRY  
      && states[right] != State.EATING) {        
     states[current] = State.EATING;          
     condition[current].signal();           
    }                  
}                   
}                      

Почему ступени не работают одновременно? Спасибо за помощь! EDIT: Для того, чтобы запустить его, есть драйвер, который заключается в следующем:

public class Lunch {                

public static void main(String[] args) {          

    ReentrantLock lock = new ReentrantLock();        
    Thread[] diners = new Thread[PhilosopherInterface.DINERS];    
    Condition[] table = new Condition[PhilosopherInterface.DINERS];   
    State[] states = new State[PhilosopherInterface.DINERS];     
    for(int i=0; i<PhilosopherInterface.DINERS; i++) {      
     states[i] = State.THINKING;           
    }                  


    for(int i=0; i<PhilosopherInterface.DINERS; i++) {      
     Diner diner = new Diner(lock, i+1, table, states);     
     diners[i] = new Thread(diner);          
     diners[i].start();             

    }                  



}                   

}           

EDIT2: Разобрался проблемы, ответы ниже.

+0

Я отредактировал оригинальный пост с драйвером. – user2751164

+1

Должна быть еще одна группа философов, чем те, которые я знаю, или они изменили свои привычки в столовой .... Те, кого я знаю, соревнуются за ложкой и вилкой и стараются последовательно приобретать оба ресурса, чтобы поесть, что может привести к тупиковой ситуации, когда один удерживает мьютекс, представляющий вилку, а другой удерживает мьютекс, представляющий ложку, каждый из которых пытается получить соответствующий другой. – BitTickler

+0

Ваши методы 'think()' и 'eat()' каждый вычисляют 'timeToSleep', но затем не используют его. Оба они всегда спят полсекунды. Это было намеренно? –

ответ

3

Говорить о ваших потоках, чтобы ждать, не заставляет их работать одновременно. Если поток должен следовать нескольким шагам перед тем, как активируется другой, то эти методы (этапы) должны быть синхронизированы.

+0

Есть ли способ сделать это, не используя Synchronized? Я предпочел бы использовать переменные состояния Java, чем использовать это. – user2751164

+0

Хотел бы я подробно остановиться на вашем вопросе, но мои знания не бесконечны. Вопрос для вас, почему вы не хотите использовать синхронизацию? Изменить: и вместо этого использовать переменные состояния java? – Josephus87

+0

@ user2751164 не существует возможности не использовать синхронизированную или какую-либо другую форму синхронизации (барьеры или затворы), если ваш поток должен выполняться в определенном порядке __and__ одновременно. Условные утверждения для однопоточного потока. –

-1

Попробуйте использовать ExecutorService. Используйте ExecutorService.submit(Runnable) и ExecutorService.shutdown(), которые будут ждать до тех пор, пока все Runnable s не завершили и не завершили работу ExecutorService.

0

Я только заблокировал один раз в начале takeChopsticks() и разблокирован в конце replaceChopsticks(), заставляя поток делать все до разблокировки.

Я использовал методы lock() и unlock() в начале и конце обоих меток takeChopsticks() и replaceChopsticks(), позволяя ему запускать одновременно.

Смежные вопросы