126-多线程下的生产者消费者模型,以及详细介绍notifyAll方法

public final void wait()方法

使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。此方法的行为就像完全执行调用wait(0)一样。

当前线程必须拥有该对象的监视器。线程释放此监视器的所有权,并等待直到另一个线程通过调用notify方法或notifyAll方法通知等待在此对象监视器上等待的线程唤醒。然后,线程等待,直到它可以重新获得监视器的所有权并恢复执行(即可运行状态)。

public final void notify()方法

唤醒正在此对象的监视器上等待的单个线程。如果有任何线程在此对象上等待,则选择其中一个唤醒。选择是任意的,并且可以根据实现情况进行选择。线程通过调用其中一个wait方法在对象的监视器上等待。

public final void notifyAll()方法

唤醒正在此对象的监视器上等待的所有线程。线程通过调用其中一个wait方法在对象的监视器上等待。

改造多线程下的生产者-消费者模型:

public void produce() {
    synchronized (LOCK) {
        // 分析此处为什么使用while,而不是用if?
        while (isProduced) {
            LOCK.wait();
        }
        System.out.println(Thread.currentThread().getName() + "->" + (++i));
        LOCK.notifyAll();
        isProduced = true;
    }
}
public void consume() {
    synchronized (LOCK) {
        while (!isProduced) {
            LOCK.wait();
        }
        System.out.println(Thread.currentThread().getName() + "->" + i);
        LOCK.notifyAll();
        isProduced = false;
    }
}
public static void main(String[] args) {
    ProduceConsumerVersion3 pc = new ProduceConsumerVersion3();
    Stream.of("P1", "P2", "P3").forEach(n -> new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                pc.produce();
                Thread.sleep(10);
            }
        }
    }, n).start());

    Stream.of("C1", "C2", "C3", "C4").forEach(n -> new Thread(() -> {
        while (true) {
            pc.consume();
            Thread.sleep(10);
        }
    }, n).start());
}

分析此处为什么使用while,而不是用if?

while (isProduced) {
    LOCK.wait();
}

notifyAll()方法将会唤醒所有的生产者线程。

如果使用if():线程A先抢到锁,运行时判断有没有生产数据,无则生产数据并运行完成,当它再次抢锁运行时发现已经生产过数据则会进行wait()操作;线程B抢到锁运行时将会跳过判断直接生产数据,从而造成了消费者还没有消费完数据又重复生产。

例:生产两次消费一次,生产一次消费两次

P2->2
P3->3
C3->3
P1->4
C4->4
C2->4

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com

文章标题:126-多线程下的生产者消费者模型,以及详细介绍notifyAll方法

文章字数:606

本文作者:神秘的小岛岛

发布时间:2019-11-30, 17:33:41

最后更新:2019-12-01, 16:10:35

原始链接:https://www.tuyrk.cn/wang-thread/126-multi-thread-notifyall/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏