原理解析
实现该模型的关键点在于使用wait()和notify()方法进行线程的切换,话不多说,直接上代码
缓存类
/**
* @Author: guanghui
* @DateTime: 2021/9/18 15:15
*/
public class Quene {
//用于判断数组是否满了
private int index=0;
//数组长度
private int size=10;
//用于存储数据
private Byte[] bytes;
public Quene(int size){
this.size=size;
this.bytes=new Byte[size];
}
//生产数据
public synchronized void push(byte c) throws InterruptedException {
while(index==size){
//数据存满了,需要进入阻塞状态
System.out.println("数据满了,通知消费执行");
//哪个线程调用push方法就会被阻塞
this.wait();
}
//赋值
bytes[index]=c;
//自增
index++;
//已经生产了数据,通知消费者消费
this.notify();
}
//消费数据
public synchronized void pop() throws InterruptedException {
while(index==0){
//数据消费完了
System.out.println("数据消费完了,通知生产者生产");
this.wait();
}
index--;
this.notify();
}
}
生产者
import lombok.SneakyThrows;
import java.util.Random;
/**
* @Author: guanghui
* @DateTime: 2021/9/18 14:42
*/
public class Provider implements Runnable{
private Quene quene;
public Provider(Quene quene){
this.quene=quene;
}
//不想写try catch
@SneakyThrows
@Override
public void run() {
for (int i=0;i<10;i++){
quene.push((byte) i);
System.out.println("生产"+i);
}
}
}
消费者
package com.guanghui.provider.thread;
import lombok.SneakyThrows;
/**
* @Author: guanghui
* @DateTime: 2021/9/18 14:52
*/
public class Consumer implements Runnable{
private Quene quene;
public Consumer(Quene quene){
this.quene=quene;
}
@SneakyThrows
@Override
public void run() {
for (int i=0;i<10;i++){
quene.pop();
System.out.println("消费"+i);
}
}
}
测试类
/**
* @Author: guanghui
* @DateTime: 2021/9/18 14:59
*/
public class Test {
public static void main(String[] args){
Quene q=new Quene(10);
Thread threadC=new Thread(new Consumer(q));
Thread threadP=new Thread(new Provider(q));
threadC.start();
threadP.start();
}
}
输出结果
我们可以看到控制台打印的生产一个数据消费一个数据,在打印时间上可能会有误差,但是实际执行流程是顺序的。这是一个最简单的实现生产者消费者模型的方法,关键点在于理解wait()和notify()运行机制。