美文网首页
wait-notify 实现生产者消费者模式

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

作者: 咪雅先森 | 来源:发表于2021-09-25 19:25 被阅读0次

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

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

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

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

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

    二、wait、notify 简单应用示例

    Wait 类

    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 类

    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

    /**
     * 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 状态,等待唤醒。

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

    相关文章

      网友评论

          本文标题:wait-notify 实现生产者消费者模式

          本文链接:https://www.haomeiwen.com/subject/ataxnltx.html