Reputation: 1619
the code at the bottom (1) was just for exercising but makes me curious why always the same Thread and only this Thread is able to receive the resource made by the producer. When I update the producer part with a Thread.sleep in my code like (2) all Threads get the resource randomly (I think). But why? Does the Sheduler works with LIFO? Or whats the "problem" here?
1
public class ProducerConsumer {
private static int resource = 0;
private static AtomicInteger id = new AtomicInteger();
public static void main(String... args) throws InterruptedException {
final Object monitor = new Object();
Runnable producer = () -> {
try {
while (!Thread.interrupted()) {
// produce number
println("producing ...");
int number = (int) (Math.random() * 1000) + 1;
Thread.sleep(number);
println("produced " + number);
// send number
synchronized (monitor) {
resource = number;
println("notified");
monitor.notifyAll();
}
}
} catch (InterruptedException e) {
println("interrupted");
}
};
Runnable consumer = () -> {
final int innerId = id.getAndIncrement();
try {
while (!Thread.interrupted()) {
// receive number
int number;
synchronized (monitor) {
while (resource == 0) {
println(innerId + " waiting ...");
monitor.wait();
println(innerId + " woke up ...");
}
number = resource;
resource = 0;
}
// consume number
println("consumed " + number);
}
} catch (Exception e) {
println("interrupted");
}
};
new Thread(producer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
new Thread(consumer).start();
Thread.sleep(10_000);
Thread.currentThread().getThreadGroup().interrupt();
}
}
2
Runnable producer = () -> {
try {
while (!Thread.interrupted()) {
// produce number
println("producing ...");
final int number = (int) (Math.random() * 1000) + 1;
Thread.sleep(number);
println("produced " + number);
synchronized (monitor) {
setResource(number);
println("notified");
Thread.sleep(100);
monitor.notifyAll();
}
}
} catch (InterruptedException e) {
println("interrupted");
}
};
Upvotes: 1
Views: 162
Reputation: 1479
It is pseudo-random.
From the notifyAll doc:
The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
The implementation seems to fairly reliable (not random) in your case, but like the documentation says, it is not 100% reliable.
Upvotes: 1