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