После столь долгого изучения модели производитель/потребитель я наконец понял это сегодня.Прежде чем писать, я сделаю обзор производителя/потребителя.
Режим производитель/потребитель — это классическая проблема синхронизации процессов в операционной системе, которая может быть решена с помощью механизма «семафор», моменты, требующие внимания, указаны ниже.
Прежде чем писать, проанализируйте, что нужно сделать:
- Определите очередь кеша, выберите набор для кэширования и сделайте в кеше только две вещи: сохраните данные и извлеките данные.
- Определите поток производителя для создания данных и сохранения их в кеше.
- Определите потребителя для извлечения данных из кеша
метод первый
Использовать LinkedHashMap в качестве кеша, синхронизированного в качестве блокировки синхронизации
определить очередь кэша
public class PublicQueue<T> {
//数据插入的下标
private int putIndex = 0;
//最大容量
private int maxCount = 50;
//缓冲区
private LinkedHashMap<Integer, T> linkedHashMap = new LinkedHashMap<>();
/**
* 往阻塞队列添加数据
* @param msg
*/
public synchronized void put(T msg) {
//如果缓存的数据达到maxCount,阻塞
if (linkedHashMap.size() == maxCount) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//没有满,就唤醒其他所有线程
notifyAll();
}
//往缓存里面存数据
linkedHashMap.put(putIndex, msg);
System.out.println("生产一个产品,当前商品下标为:"+putIndex+"===文本为:"+msg+"===缓存长度为:"+linkedHashMap.size());
//更新putIndex
putIndex = (putIndex + 1 >= maxCount) ? (putIndex + 1) % maxCount : putIndex + 1;
}
/***
* 从阻塞队列取数据
* @return
*/
public synchronized T get() {
//如果阻塞队列为空,就阻塞消费者
if (linkedHashMap.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
notifyAll();
}
//通过Iterator取数据,确保取出的数据是有序的
Iterator iterator = linkedHashMap.entrySet().iterator();
T t = null;
if (iterator.hasNext()) {
Map.Entry<Integer, T> entry = (Map.Entry<Integer, T>) iterator.next();
t = entry.getValue();
int index = entry.getKey();
linkedHashMap.remove(index);
System.out.println("消费一个产品,当前商品下标为:"+index+"===文本为:"+ t +"===缓存长度为:"+linkedHashMap.size());
}
return t;
}
}
Определить поток производителя
public class Provider extends Thread{
private PublicQueue publicQueue;
public Provider(PublicQueue publicQueue) {
this.publicQueue = publicQueue;
}
@Override
public void run() {
for (int i = 0; i < 60; i++) {
publicQueue.put(String.valueOf(i));
}
}
}
определить потребительский поток
public class Consumer extends Thread{
private PublicQueue publicQueue;
public Consumer(PublicQueue publicQueue) {
this.publicQueue = publicQueue;
}
@Override
public void run() {
for (; ; ) {
publicQueue.get();
}
}
}
контрольная работа
public class ProviderConsumerTest {
public static void main(String[] args) {
PublicQueue publicQueue = new PublicQueue();
Provider provider = new Provider(publicQueue);
Consumer consumer = new Consumer(publicQueue);
provider.start();
consumer.start();
}
}
Способ 2
Этот метод также относительно прост, вы можете напрямую использовать очередь блокировки, предоставляемую Java.
public class PublicQueue<T> {
//缓冲区
private BlockingDeque<T> blockingDeque = new LinkedBlockingDeque<>(50);
public void add(T msg){
try {
blockingDeque.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产一个产品,当前商品下标为:"+"===文本为:"+msg);
}
public T get(){
T t = null;
try {
t = blockingDeque.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费一个产品,当前商品下标为:"+"===文本为:"+t);
return t;
}
}