文章目录
声明:
本博客是本人在学习《Java 多线程编程核心技术》后整理的笔记,旨在方便复习和回顾,并非用作商业用途。
本博客已标明出处,如有侵权请告知,马上删除。
3.1 等待/通知机制
3.1.11 生产者/消费者模式实现
等待/通知模式最经典的案例就是 “生产者/消费者” 模式。但此模式在使用上有几种 “变形”,还有—些小的注意事项,但原理都是基于 wait/notify 的。
3.1.11.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(); } } }
-
创建消费者
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(); } } }
-
创建存储值的对象
public class ValueObject { public static String value = ""; }
-
创建两个自定义的线程类
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(); } } }
-
测试类
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 状态,则程序就不再执行任何业务功能了,整个项目呈停止状态。这在生产者与消费者模式中经常遇到。
-
创建生产者
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(); } } }
-
创建消费者
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(); } } }
-
创建存储值的对象
public class ValueObject { public static String value = ""; }
-
创建两个自定义的线程类
public class