Философы, как это часто бывает, очень бедны, и они смогли позволить себе приобрести лишь пять палочек (или в более общем виде — количество палочек совпадает с количеством философов). Последние разложены кругом по столу, между философами. Когда философу захочется поесть, ему придется взять палочку слева и справа. Если с какой-либо стороны желаемая палочка уже в руке другого философа, только что оторвавшемуся от размышлений придется подождать ее освобождения:
//: concurrency/Chopstick.java
// Палочки для обедающих философов.
public class Chopstick {
private boolean taken = false;
public synchronized
void takeO throws InterruptedException { while(taken)
waitO; taken = true;
}
public synchronized void dropO { taken = false; notifyAllО;
}
Два философа (Philosopher) ни при каких условиях не смогут успешно взять (takeQ) одну и ту же палочку (Chopstick) одновременно. Если один философ уже взял палочку, другому философу придется подождать (wait()), пока она не будет освобождена текущим пользователем (drop()).
Когда задача Philosopher вызывает take(), она ожидает, пока флаг taken не перейдет в состояние false (то есть пока палочка не будет освобождена тем философом, который держит ее в данный момент). Далее задача устанавливает флаг taken равным true, показывая тем самым, что палочка занята. Завершив работу с Chopstick, Philosopher вызывает drop(), чтобы изменить флаг и оповестить (notifyAll()) всех остальных философов, ожидающих освобождения палочки:
// concurrency/Philosopher java // Обедающий философ import java.util concurrent *. import java util *,
import static net mindview util Print *;
public class Philosopher implements Runnable { private Chopstick left, private Chopstick right, private final int id, private final int ponderFactor; private Random rand = new Random(47). private void pauseO throws InterruptedException { if(ponderFactor == 0) return. TimeUnit MILLISECONDS sleep(
rand.nextInt(ponderFactor * 250));
}
public Philosopher(Chopstick left. Chopstick right, int ident, int ponder) { this.left = left; this right = right; id = ident,
ponderFactor = ponder;
}
public void run() { try {
while(IThread interruptedO) {
print(this + " " + "думает"), pauseO,
// Философ проголодался
print(this + " " + "берет правую").
right takeO.
print(this + " " + "берет левую"); left. takeO.
print(this + " " + "ест"); pauseO; right dropO; left.dropO.
}
} catchdnterruptedException e) {
print(this + " " + "выход через прерывание"),