等待/通知模式最经典的案例就是”生产者/消费者“模式。但此模式在使用上有几种”变形“,还有一些小的注意事项,但原理都是基于wait/notify的。
1.一生产和一消费:操作值
示例代码:
对象:
package entity;
/**
* @Author LiBinquan
*/
public class ValueObject {
public static String value = "";
}
类P:
package entity;
/**
* @Author LiBinquan
*/
public class P {
private String lock;
public P(String lock){
super();
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();
}
}
}
类C:
package entity;
import sun.awt.SunHints;
/**
* @Author LiBinquan
*/
public class C {
private String lock;
public C(String lock){
super();
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();
}
}
}
线程P:
package entity;
import volatileTest.ThreadAdd;
/**
* @Author LiBinquan
*/
public class ThreadP extends Thread {
private P p;
public ThreadP(P p){
super();
this.p = p;
}
@Override
public void run() {
while (true){
p.setValue();
}
}
}
线程C:
package entity;
/**
* @Author LiBinquan
*/
public class ThreadC extends Thread{
private C r;
public ThreadC(C r){
super();
this.r = r;
}
@Override
public void run() {
while (true){
r.getValue();
}
}
}
运行类:
package entity;
/**
* @Author LiBinquan
*/
public class Run {
public static void main(String[] args) {
String lock = "";
P p = new P(lock);
C r = new C(lock);
ThreadP threadP = new ThreadP(p);
ThreadC threadC = new ThreadC(r);
threadP.start();
threadC.start();
}
}
输出:
本示例中是1个生产者和1个消费者进行数据的交互,在控制台中打印的日志get和set是交替运行的。
但如果在此实验的基础上,设计出多个生产者和多个消费者,呢么在运行的过程中极有可能出现”假死“的情况,也就是所有的线程都呈等待状态。
2.多生产者与多消费者:操作值 - 假死
”假死“的现象其实就是线程进入等待状态。如果全部线程都进入等待状态,则程序就不再执行任何业务功能了,整个项目呈停止状态。这在使用生产者与消费者模式时经常遇到。
修改后代码:
类P:
package entity;
/**
* @Author LiBinquan
*/
public class P {
private String lock;
public <