124-线程间通信快速入门,使用wait和notify进行线程间的数据通信

线程通信例子:线程A负责从数据库读取数据,线程B负责分析处理数据。当线程A获取到数据并放入内存后需要通知线程B去处理数据。线程A为生产者,线程B为消费者

版本1:生产者一直负责生产,消费者一直负责消费。没有进行通信,生产者生产完毕没有通知消费者,消费者也不知道是否是最新数据、是否已经消费过。

public class ProduceConsumerVersion1 {
    private int i = 1;

    private final Object LOCK = new Object();
    private void produce() {
        synchronized (LOCK) {
            System.out.println("P->" + (i++));
        }
    }
    private void consume() {
        synchronized (LOCK) {
            System.out.println("C->" + (i));
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion1 pc = new ProduceConsumerVersion1();
        new Thread(() -> {
            while (true) {
                pc.produce();
            }
        }, "P").start();
        new Thread(() -> {
            while (true) {
                pc.consume();
            }
        }, "C").start();
    }
}

运行代码会发现,有些时候线程P不断生产数据,而线程C没有消费;而有些时候线程C只消费最新的数据,并且不断重复的消费最新数据。

造成这种情况的原因是:线程间没有进行通信。

版本2:生产者负责生产,生产完毕之后通知消费者,如果没有消费则不再进行生产。消费者负责消费,有数据则进行消费,没有数据则进行等待。

public class ProduceConsumerVersion2 {
    private int i = 0;
    private final Object LOCK = new Object();
    // 是否已经消费
    private volatile boolean isProduced = false;

    public void produce() {
        synchronized (LOCK) {
            if (isProduced) {
                LOCK.wait();
            } else {
                System.out.println("P->" + (++i));
                LOCK.notify();
                isProduced = true;
            }
        }
    }
    public void consume() {
        synchronized (LOCK) {
            if (isProduced) {
                System.out.println("C->" + i);
                LOCK.notify();
                isProduced = false;
            } else {
                LOCK.wait();
            }
        }
    }

    public static void main(String[] args) {
        ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();

        new Thread(() -> {
            while (true) {
                pc.produce();
            }
        }, "P").start();
        new Thread(() -> {
            while (true) {
                pc.consume();
            }
        }, "C").start();
    }
}

此代码实现了简单的生产者-消费者模型,但是在多个生产者、消费者线程运行时,会产生一些问题。思考问题是什么?欲知后事如何,且听下回分解。


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

文章标题:124-线程间通信快速入门,使用wait和notify进行线程间的数据通信

文章字数:496

本文作者:神秘的小岛岛

发布时间:2019-11-30, 15:28:42

最后更新:2019-11-30, 16:21:08

原始链接:https://www.tuyrk.cn/wang-thread/124-wait-notify/

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

目录
×

喜欢就点赞,疼爱就打赏