生产消费者模型
1.在模型中,负责生产数据的模块是生产者,使用数据的是消费者
需要的是现有生产者去生产数据,然后才能有消费者去消费数据。
没有数据时候需要等待,消费者需要进行等待。
同时生产者,也需要等待消费者消费完了产品再进行生产。
1.首先写共享数据的那个类
这就是作为共享数据的类,用这个类的同一个对象作为锁锁住数据
package org.example.testjul;
public class ValueOf {
private String value = "";
public void setValue(){
synchronized (this){
if(!value.equals("")){
//如果value不是是空串,那么就等待,毕竟为空时候加值才有意义
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
StringBuffer sb = new StringBuffer();
sb.append(System.currentTimeMillis());
sb.append("->");
sb.append(System.nanoTime());
System.out.println("设置的值就是i" + sb.toString());
this.value = sb.toString();
this.notify();//有可能是沉睡的,所以我们需要进行唤醒服务
}
}
public void getValue(){
//获得这个字段值
synchronized (this){
//还是用同一个对象作为锁
if(this.value.equals("")){
//当value是空的的时候
//获取不到任何东西
try {
this.wait();//让这时候来调用的线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果不是空那么线程直接获取到数值
System.out.println("获取到数据是" + this.value);
this.value = "";//设置为空,因为取走的数值
this.notify();//让沉睡线程醒过来
}
}
}
2.设置生产者和消费者线程
package org.example.testjul;
public class producedata extends Thread {
//这就是生产者,生产数据的
private ValueOf produce;
public producedata(ValueOf produce) {
this.produce = produce;//必须是同一把锁,我们将对象看做是一把锁,那么就必须是同一个对象才行,同一个对象
//作为一把锁,进出同一个同步代码块才有意义
}
@Override
public void run(){
while(true){
produce.setValue();//一直作为生产者调用生产方法
}
}
}
package org.example.testjul;
public class consumption extends Thread{
private ValueOf value;
public consumption(ValueOf value) {
this.value = value;
}
@Override
public void run() {
while (true){
value.getValue();
//消费者就是一个不断调用消费线程
}
}
}
测试类,记得是同一个对象作为锁哦
package org.example.testjul;
public class Test {
public static void main(String[] args) {
//生产者和消费者中,那个成员变量必须统一起来,然后用一把锁去给锁住
ValueOf valueOf = new ValueOf();//这个类的,同一个对象,就是一把锁
producedata producedata = new producedata(valueOf);
consumption consumption = new consumption(valueOf);
//生产消费者线程
producedata.start();//记得先生产然后消费哦
consumption.start();
//这样生产消费,永不停歇,记住,同一个对象才能锁住,同一个代码区。锁只能有一把,有多吧就出事了。
}
}
这个那个先启动后启动没有关系的
为什么呢,因为wait并不会控制锁,wait会释放锁的,也就是说无论谁沉睡了,都会被叫醒的。
上面那是一个生产者,一个消费者情况,我们最终要测试的事多个生产者,多个消费者的情况。
多个生产者和消费者情况下,一定要使用notifyAll这个命令
明白不,不然每次随机唤醒一个线程,结果发现这个线程字符串还是空的,结果这个线程又沉睡了。你随机唤醒那个线程,无论是生产者还是消费者,都有可能是空的,然后这次就就浪费了
有可能进入假死状态notify在多个生产消费者时候,假死了
所有生产者和消费者都进入wait状态了,没人去唤醒所有人了。
工作中wait那个判断条件最好用while循环
被唤醒后,最好去判断一下,自己符合不符合条件,因为大家都被锁住了,谁不不能保证谁一定被唤醒了。
让您醒来之后,重新判断一下自己是不是符合标准。
两个线程交替打印。上面那个是使用synorcized打印的,我们接下来要使用Lock锁进行
lock锁重点在于要先获得锁对象
然后我们需要condition对象,可以唤醒指定线程。