《Java 多线程编程核心技术》笔记——第3章 线程间通信(二)

本文是学习《Java多线程编程核心技术》的笔记,重点讲解了生产者/消费者模式的实现,包括单生产者单消费者、多生产者多消费者的情况,以及如何避免假死现象。通过实例分析了使用wait/notify机制以及管道流进行线程间通信的方法,并展示了实战中如何实现线程的交替执行。
摘要由CSDN通过智能技术生成

声明:

本博客是本人在学习《Java 多线程编程核心技术》后整理的笔记,旨在方便复习和回顾,并非用作商业用途。

本博客已标明出处,如有侵权请告知,马上删除。

3.1 等待/通知机制

3.1.11 生产者/消费者模式实现

等待/通知模式最经典的案例就是 “生产者/消费者” 模式。但此模式在使用上有几种 “变形”,还有—些小的注意事项,但原理都是基于 wait/notify 的。

3.1.11.1 一生产与一消费:操作值

  1. 创建生产者

    public class P {
         
        private String lock;
    
        public P(String lock) {
         
            this.lock = lock;
        }
    
        public void setValue() {
         
            try {
         
                synchronized (lock) {
         
                    if (!ValueObject.value.equals("")) {
         
                        lock.wait();
                    }
                    String value = System.currentTimeMillis() + "_" + System.nanoTime();
                    System.out.println("set的值是 " + value);
                    ValueObject.value = value;
                    lock.notify();
                }
            } catch (InterruptedException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  2. 创建消费者

    public class C {
         
        private String lock;
    
        public C(String lock) {
         
            this.lock = lock;
        }
    
        public void getValue() {
         
            try {
         
                synchronized (lock) {
         
                    if (ValueObject.value.equals("")) {
         
                        lock.wait();
                    }
                    System.out.println("get的值是" + ValueObject.value);
                    ValueObject.value = "";
                    lock.notify();
                }
            } catch (InterruptedException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  3. 创建存储值的对象

    public class ValueObject {
         
        public static String value = "";
    }
    
  4. 创建两个自定义的线程类

    public class ThreadP extends Thread {
         
        private P p;
    
        public ThreadP(P p) {
         
            this.p = p;
        }
    
        @Override
        public void run() {
         
            while (true) {
         
                p.setValue();
            }
        }
    }
    
    public class ThreadC extends Thread {
         
        private C c;
    
        public ThreadC(C c) {
         
            this.c = c;
        }
    
        @Override
        public void run() {
         
            while (true) {
         
                c.getValue();
            }
        }
    }
    
  5. 测试类

    public class Run {
         
        public static void main(String[] args) {
         
            String lock = new String("");
            P p = new P(lock);
            C c = new C(lock);
            ThreadP threadP = new ThreadP(p);
            ThreadC threadC = new ThreadC(c);
            threadP.start();
            threadC.start();
        }
    }
    

    运行结果

    set的值是 1598153478124_582806771523454
    get的值是1598153478124_582806771523454
    set的值是 1598153478125_582806771741231
    get的值是1598153478125_582806771741231
    set的值是 1598153478125_582806771782120
    get的值是1598153478125_582806771782120
    ...
    

    分析:本示例是 1 个生产者和 1 个消费者进行数据的交互,在控制台中打印的日志 get 和 set 是交替运行的。但如果在此实验的基础上,设计出多个生产者和多个消费者,那么在运行的过程中极有可能出现 “假死” 的情况,也就是所有的线程都呈 WAITING 等待状态。

3.1.11.2 多生产与多消费:操作值——假死

“假死” 的现象其实就是线程进入 WAITING 等待状态。如果全部线程进入 WAITING 状态,则程序就不再执行任何业务功能了,整个项目呈停止状态。这在生产者与消费者模式中经常遇到。

  1. 创建生产者

    public class P {
         
        private String lock;
    
        public P(String lock) {
         
            this.lock = lock;
        }
    
        public void setValue() {
         
            try {
         
                synchronized (lock) {
         
                    while (!ValueObject.value.equals("")) {
         
                        System.out.println("生产者 " + Thread.currentThread().getName() + " WAITING");
                        lock.wait();
                    }
                    System.out.println("生产者 " + Thread.currentThread().getName() + " RUNNABLE");
                    ValueObject.value = System.currentTimeMillis() + " - " + System.nanoTime();
                    lock.notify();
                }
            } catch (InterruptedException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  2. 创建消费者

    public class C {
         
        private String lock;
    
        public C(String lock) {
         
            this.lock = lock;
        }
    
        public void getValue() {
         
            try {
         
                synchronized (lock) {
         
                    while (ValueObject.value.equals("")) {
         
                        System.out.println("消费者 " + Thread.currentThread().getName() + " WAITING");
                        lock.wait();
                    }
                    System.out.println("消费者 " + Thread.currentThread().getName() + " RUNNABLE");
                    ValueObject.value = "";
                    lock.notify();
                }
            } catch (InterruptedException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  3. 创建存储值的对象

    public class ValueObject {
         
        public static String value = "";
    }
    
  4. 创建两个自定义的线程类

    public class 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bm1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值