首页 > 解决方案 > wait() 和 notifyAll() 的奇怪行为

问题描述

我发现自己对 wait() 和 notifyAll() 的这种行为感到困惑:

import java.util.LinkedList;
import java.util.Queue;

class Producer implements Runnable {

    Queue<Integer> sharedMessages;
    Integer i = 0;
    Producer(Queue<Integer> sharedMessages) {
        this.sharedMessages = sharedMessages;
    }

    public void produce(Integer i) {
        synchronized (sharedMessages){
            System.out.println("Producing message " + i);
            this.sharedMessages.add(i);
        }
    }

    public void run(){
        synchronized (sharedMessages) {
            while (i < 100) {
                produce(i++);
            }
        }
    }
}

消费者:

class Consumer implements Runnable{

    Queue<Integer> sharedMessages;
    Consumer(Queue<Integer> sharedMessages) {
        this.sharedMessages = sharedMessages;
    }

    public void consume() {
        synchronized (sharedMessages) {
                System.out.println(sharedMessages.remove() + " consumed by " + Thread.currentThread().getName().toString());
            
        }
    }

    @Override
    public void run(){
        synchronized (sharedMessages){
            while(sharedMessaged.size() > 0){
                System.out.println(Thread.currentThread().getName() + " going to consume");
                consume();
                try {
                    sharedMessages.wait();
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + ": I was interrupted from my sleep!");
                }
                sharedMessages.notifyAll();
            }
        }
    }
}

这是我创建线程的方式:

public class Main {
    public static void main(String[] args) {
        Queue<Integer> sharedMessages = new LinkedList<>();

        new Thread(new Producer(sharedMessages)).start();

        new Thread(new Consumer(sharedMessages)).start();
        new Thread(new Consumer(sharedMessages)).start();
        new Thread(new Consumer(sharedMessages)).start();
        new Thread(new Consumer(sharedMessages)).start();
        new Thread(new Consumer(sharedMessages)).start();
        new Thread(new Consumer(sharedMessages)).start();
    }

}

输出看起来像这样:

Producing message 0
Producing message 1
...
Producing message 98
Producing message 99
Thread-6 going to consume
0 consumed by Thread-6
Thread-5 going to consume
1 consumed by Thread-5
Thread-4 going to consume
2 consumed by Thread-4
Thread-3 going to consume
3 consumed by Thread-3
Thread-2 going to consume
4 consumed by Thread-2
Thread-1 going to consume
5 consumed by Thread-1

然后应用程序继续运行,在 5 之后没有消费者消费任何消息。

由于wait()notifyAll()是在同一个监视器上创建的sharedMessages,并且 while 循环继续运行,消费者线程不应该继续运行,或者消费消息吗?

注意:这个问题不是关于有界阻塞队列/典型的生产者消费者。我正在努力更好地理解wait()notifyAll这种行为引起了我的注意。我可能在这里遗漏了一些东西,我正在寻找答案,指出我遗漏了什么,而不是另一种方式。

标签: javamultithreading

解决方案


您的Producer线程锁定队列,然后添加 100 条消息而不释放锁,最后在终止之前释放锁,而不通知任何人。

您的 6 个Consumer线程将分别使用一条消息,然后调用wait().

至此,Producer线程已经结束,6个Consumer线程都在等待。

你设想谁会通知他们叫醒他们?


推荐阅读