• Java基础进阶多线程-生产者和消费者模式


    1、什么是“生产者和消费者模式”?

    • 生产线程负责生产,消费线程负责消费
    • 生产线程和消费线程要达到均衡
    • 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方法

    2、wait和notify方法不是线程对象的方法,是普通java对象都有的方法
    3、wait和notify方法建立在线程同步的基础之上因为多线程要同时操作一个仓库有线程安全问题
    4、wait方法作用:o.wait()让正在o对象上活动的线程t进入等待状态并且释放掉t线程之前占有的o对象的锁
    5、notify方法作用:o.notify()让正在o对象上等待的线程唤醒,只是通知,不会释放o对象上之前占有的锁
    6、模拟需求:

    • 仓库我们采用List集合
      List集合中假设只能存储一个元素
      1个元素就表示仓库满l
      如果List集合中元素个数是0,就表示仓库空了
      保证List集合中永远都是最多存储一个元素了
      必须做到,生产一个,消费一个
      在这里插入图片描述
      在这里插入图片描述

    示例代码01:

    public class ThreadTest16 {
    
        public static void main(String[] args) {
    
            //创建一个仓库对象,共享的
            List list = new ArrayList();
            //创建对象
            //创建生产者对象
            Thread t1 = new Producter(list);
            //创建消费者对象
            Thread t2 = new Consumer(list);
            t1.setName("生产者线程");
            t2.setName("消费者线程");
    
            //启动线程
            t1.start();
            t2.start();
        }
    }
    
    //生产者线程
    class Producter extends Thread{
        private List list;
        public Producter(List list){
            this.list = list;
        }
    
        public void run(){
    
            while(true) {
                synchronized (list) {
                    if (list.size() > 0) {
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    Object obj = new Object();
                    list.add(obj);
                    System.out.println(Thread.currentThread().getName() + "--->" + obj);
                    //线程唤醒
                    list.notifyAll();
                }
            }
        }
    }
    
    //消费者线程
    class Consumer extends Thread{
    
        private List list;
        public Consumer(List list){
            this.list = list;
        }
        public void run(){
    
            while(true){
                synchronized (list) {
                    if (list.size() == 0) {
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    Object obj = list.remove(0);
                    System.out.println(Thread.currentThread().getName() + "--->" + obj);
                    list.notifyAll();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    运行结果:

    在这里插入图片描述

    使用生产者和消费者模式实现,交替输出:
    假设只有两个线程,输出以下结果:

    • t1—>1
      t2—>2
      t3—>3
      t4—>4
      t5—>5
      t6—>6
      t7—>7
      要求:必须交替执行,并且t1线程负责输出奇数,t2线程输出偶数
      两个线程共享一个数字,每个线程执行时都要对这个数字进行:++

    示例代码02:

    public class ThreadTest {
        public static void main(String[] args) {
    
            //创建数字类对象
            Num num = new Num();
            //创建生产者对象
            Thread t1 = new Producter(num);
    
            //创建消费者对象
            Thread t2 = new Consumer(num);
    
            //修改线程名字
            t1.setName("t1");
            t2.setName("t2");
    
            //启动线程
            t1.start();
            t2.start();
    
        }
    }
    
    //共享数据
    class Num{
        int i = 1;
    
    
    }
    //生产者线程
    class Producter extends Thread{
    
        private Num num;
        public Producter(Num num){
            this.num = num;
        }
        public void run(){
    
            while(true){
                synchronized (num) {
                    if ((num.i % 2) == 0) {
                        try {
                            num.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "--->" + num.i++);
                    try {
                        //延迟1秒输出
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num.notifyAll();
                }
            }
        }
    }
    //消费者线程
    class Consumer extends Thread{
    
        private Num num;
        public Consumer(Num num){
            this.num = num;
        }
        public void run(){
    
            while(true){
                synchronized (num) {
                    if ((num.i % 2) == 1) {
                        try {
                            num.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "--->" + num.i++);
                    try {
                        //延迟一秒输出
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num.notifyAll();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    运行结果:

    在这里插入图片描述

  • 相关阅读:
    【数据结构】优先级队列(堆)
    【JavaSE】String类总结,StringBuilder、StringBuffer、String的区别讲解
    RFM分析 | 一招搞定精细化客户管理,盒马鲜生等企业都在用
    uni-app:实现页面效果3
    GAN详解
    MLOps:掌握机器学习部署:Docker、Kubernetes、Helm 现代 Web 框架
    Java设计模式详解:抽象工厂模式
    AUTOSAR汽车电子嵌入式编程精讲300篇-面向驾驶辅助技术融合算法的日志系统设计与实现
    揭秘 FineVideo 数据集构建的背后的秘密
    通用HttpClient封装
  • 原文地址:https://blog.csdn.net/qq_46096136/article/details/126806807