Надеюсь, это не повторный вопрос, но я рассмотрел все ответы в других вопросах, и никто не удовлетворил мою проблему.Темы не работают одновременно
У меня есть программа, которая решает проблему Обеденного Философа, и когда я запускаю программу, потоки ждут, пока следующий не будет выполнен, прежде чем запускать другую. Это приводит к тому, что вывод потока будет выглядеть следующим образом:
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: Разобрался проблемы, ответы ниже.
Я отредактировал оригинальный пост с драйвером. – user2751164
Должна быть еще одна группа философов, чем те, которые я знаю, или они изменили свои привычки в столовой .... Те, кого я знаю, соревнуются за ложкой и вилкой и стараются последовательно приобретать оба ресурса, чтобы поесть, что может привести к тупиковой ситуации, когда один удерживает мьютекс, представляющий вилку, а другой удерживает мьютекс, представляющий ложку, каждый из которых пытается получить соответствующий другой. – BitTickler
Ваши методы 'think()' и 'eat()' каждый вычисляют 'timeToSleep', но затем не используют его. Оба они всегда спят полсекунды. Это было намеренно? –