前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >wait-notify 实现生产者消费者模式

wait-notify 实现生产者消费者模式

作者头像
潇洒
发布2023-10-20 10:44:36
2610
发布2023-10-20 10:44:36
举报
文章被收录于专栏:石头岛

wait 和 nofity 在线程中的搭配使用,其实就是生产者消费者的一种应用。

一、为什么要有生产者消费者模式

在实际应使用多线程时,线程间的角色并不一完全一样的,有的线程负责生产数据,有的线程负责消费数据。所在就会有一种情况,就是: 生产者生产数据太快,消费者消费能力跟不上。

比较线程A 不断的new 对象,并将对象放到一个队列里,而线程B,不断的从队列里拿出数据进行逻辑操作。显然线程A new 对象这一操作会更快,如果一直持续下去内存有可能会被撑暴。

解决这个问题的思路之一就是:生产者-消费者模式

二、wait、notify 简单应用示例

Wait 类

代码语言:javascript
复制
public class SimpleWaitTest implements Runnable {

    private Object object;

    public SimpleWaitTest(Object object) {
        this.object = object;
    }

    @Override
    public void run() {
        testMethod(object);
    }

    public void testMethod(Object lock) {
        synchronized (lock) {
            try {
                System.out.println("testMethod begin " + Thread.currentThread().getName());
                //1. 锁住自己
                lock.wait();
                System.out.println("testMethod be notify " + Thread.currentThread().getName());
                //4.唤醒 wait 线程
                lock.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }



    public void setObject(Object object) {
        this.object = object;
    }
}

notify 类

代码语言:javascript
复制
public class SimpleNotifyTest implements Runnable {

    private Object object;

    public SimpleNotifyTest(Object object) {
        this.object = object;
    }

    @Override
    public void run() {
        syncMethod(object);
    }


    public void syncMethod(Object lock) {
        synchronized (lock) {
            try {
                System.out.println("syncMethod begin " + Thread.currentThread().getName());
                //2.唤醒 wait 线程后 wait
                lock.notify();
                //3.wait 住,等待唤醒
                lock.wait();
                System.out.println("syncMethod be notify " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

测试 wait、notify

代码语言:javascript
复制
/**
 * Created by kayle on 2016/12/16.
 */
public class Test {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        SimpleWaitTest simpleWaitTest = new SimpleWaitTest(object);
        SimpleNotifyTest simpleNotifyTest = new SimpleNotifyTest(object);

        new Thread(simpleWaitTest).start();
        Thread.sleep(100);
        new Thread(simpleNotifyTest).start();
    }
}

三、生产者消费者模式

做用在于生产者执行完生产任务后,阻塞自己再唤醒消费者进行消费。是一种线程间的协作。 下面通过一个例子,打印奇偶数来看这一过程。

效果:交替打印奇数 和 偶数

1.设计

  1. 生产类
  2. 消费类
  3. 公共标识符,独立于生产为 和 消费类

为什么要分开生产类 和 消费类,因为如果业务相同的线程,使用线程池就可以完成,不需要这么麻烦,控制两个线程的频率。 两边代码几乎相同,不同的就是 flag 的初始值不相同,为了在程序启动时,一个线程先执行,别一个线程直接进行 wait 状态,等待唤醒。

代码语言:javascript
复制
public class TwoThreadWaitNotify {
    private int start = 1;
    private boolean flag = false;
    public static void main(String[] args) {
        TwoThreadWaitNotify twoThread = new TwoThreadWaitNotify();
        Thread t1 = new Thread(new OuNum(twoThread));
        t1.setName("线程-A");

        Thread t2 = new Thread(new JiNum(twoThread));
        t2.setName("线程-B");

        t1.start();
        t2.start();
    }

    /**
     * 偶数线程
     */
    public static class OuNum implements Runnable {
        private TwoThreadWaitNotify number;
        public OuNum(TwoThreadWaitNotify number) {
            this.number = number;
        }
        @Override
        public void run() {
            while (number.start <= 100) {
                synchronized (TwoThreadWaitNotify.class) {
                    System.out.println("偶数线程抢到锁了");
                    if (number.flag) {
                        System.out.println(Thread.currentThread().getName() + "-->偶数" + number.start);
                        number.start++;
                        number.flag = false;
                        TwoThreadWaitNotify.class.notify();
                    }else {
                        try {
                            TwoThreadWaitNotify.class.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 奇数线程
     */
    public static class JiNum implements Runnable {
        private TwoThreadWaitNotify number;
        public JiNum(TwoThreadWaitNotify number) {
            this.number = number;
        }
        @Override
        public void run() {
            while (number.start <= 100) {
                synchronized (TwoThreadWaitNotify.class) {
                    System.out.println("奇数线程抢到锁了");
                    if (!number.flag) {
                        System.out.println(Thread.currentThread().getName() + "-->奇数" + number.start);
                        number.start++;
                        number.flag = true;
                        TwoThreadWaitNotify.class.notify();
                    }else {
                        try {
                            TwoThreadWaitNotify.class.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么要有生产者消费者模式
  • 二、wait、notify 简单应用示例
    • Wait 类
      • notify 类
        • 测试 wait、notify
        • 三、生产者消费者模式
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档