Java:等一下,通知

时间:2016-04-21 17:32:58

标签: java notify

底部的代码(1)只是用于锻炼,但让我好奇为什么总是相同的线程,只有这个线程能够接收生产者制作的资源。当我在我的代码中使用Thread.sleep更新生成器部分时,如(2)所有Threads随机获取资源(我认为)。但为什么? Sheduler是否与LIFO配合使用?或者是什么问题"这里吗?

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

1 个答案:

答案 0 :(得分:1)

它是伪随机的。

来自notifyAll doc:

  

唤醒的线程将以通常的方式与可能正在竞争同步此对象的任何其他线程竞争;例如,被唤醒的线程在下一个锁定此对象的线程中没有可靠的特权或劣势。

在您的情况下,实现似乎相当可靠(非随机),但正如文档所述,它并非100%可靠。

相关问题