1.数据缓存区:
public class DataBuffer {
private final List<Integer> dataBuffer = new LinkedList<>();
//缓存区最大长度
public static Integer MAX_LENTH = 1024;
public List<Integer> getDataBuffer() {
return dataBuffer;
}
}
2.生产者(模板模式)
public abstract class AbstactProduct implements Runnable{
@Override
public void run() {
while (true){
product();
}
}
//子类来实现该方法
protected abstract void product();
}
public class Product extends AbstactProduct {
private DataBuffer dataBuffer;
private AtomicInteger atomicInteger = new AtomicInteger(0);
public Product(DataBuffer dataBuffer) {
this.dataBuffer = dataBuffer;
}
@Override
protected void product() {
synchronized (dataBuffer){
//如果缓冲区满了,就停止生产
while (dataBuffer.getDataBuffer().size() == DataBuffer.MAX_LENTH){
try {
System.out.println("缓存区满了,停止生产");
dataBuffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//生产生产数据
int andIncrement = atomicInteger.getAndIncrement();
dataBuffer.getDataBuffer().add(andIncrement);
dataBuffer.notifyAll();
System.out.println("生产者生产数据:"+andIncrement);
}
}
}
AtomicInteger在多线程下也是安全的,也就意味着可以有多个线程的生产者。同时notifyAll(),wait()
都是Object的方法,需要在synchronized同步代码块中(同步方法也可以)
3.消费者(模板模式)
public abstract class AbstactConsumer implements Runnable{
@Override
public void run() {
while (true){
consumer();
try {
//休眠是为了让缓存区满
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//子类实现
protected abstract void consumer();
}
public class Consumer extends AbstactConsumer {
private DataBuffer dataBuffer;
public Consumer(DataBuffer dataBuffer) {
this.dataBuffer = dataBuffer;
}
@Override
protected void consumer() {
synchronized (dataBuffer){
while (dataBuffer.getDataBuffer().size() == 0){
try {
System.out.println(Thread.currentThread().getName()+"消费完毕,消费者等待");
dataBuffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Integer remove = dataBuffer.getDataBuffer().remove(0);
dataBuffer.notifyAll();
System.out.println(Thread.currentThread().getName()+"消费数据:"+remove);
}
}
}
多线程下的消费者会涉及到线程安全的问题,但是这里是用缓存区对象dataBuffer
来加锁进行消费的,而该对象只有一份,所以即使这里使用了LinkedList也不会有线程安全的问题。
4.开始测试
public class Test {
public static void main(String[] args) {
DataBuffer dataBuffer = new DataBuffer();
Product product = new Product(dataBuffer);
//生产者1
new Thread(product).start();
Consumer consumer = new Consumer(dataBuffer);
Consumer consumer1 = new Consumer(dataBuffer);
//消费者1启动
new Thread(consumer).start();
//消费者2启动
new Thread(consumer1).start();
}
}