生产者/消费者模式是一种非常典型的多线程场景,理解起来其实也非常简单。
我们就用最其名称的字面意思来梳理一下。
试想一下生活中的生产者,消费者是都是充当着什么样的角色?
作为一个游走在死宅边缘的异次元生物,对于手办总有一些莫名的追求。我们就用它来做场景的讲解吧。
手办的生产者--就叫他们,手作屋吧。
手办的消费者--没错,就是我,和其他死宅们。
手作屋家的叶修手办在全职高手货架,总共有10个货位。
手作屋们每制作一个手办,就会把它放进货位上;
作为叶修粉的死宅们看到上架一个手办,就会把它买走;
如果货位满了,手作屋们就不再上货新的手办,直到有人买走,货位出现空位为止;
同样的,如果手办告罄,消费者们就无法购买手办。
而这个货架呢,就是生产者/消费者模式中,常用的缓存容器了。
所以现在我们重新梳理一下,生产者/消费者模式。
必要元素:生产者,消费者,容器。
在代码中,我们经常使用栈/队列充当容器的作用。因为他们都有快速上架、销售(入栈(队)出栈(队))的方法。
好,在java中,一个面向对象编程语言,我们先来看看对象都有谁。
生产者,手作屋在自己埋头苦干,做完就上架;
消费者,瞄准货架,有货就买;
两者完全没什么关系,大家的目标都是货架罢了。
所以,我们先让生产者动起来,毕竟没有生产力,消费者再有钱也买不到。
import java.util.concurrent.BlockingQueue;
//集成Runnable接口,重写run方法。
public class Provider implements Runnable{
//货架(final是不可变的,所以这个queue是惟一的货架)
private final BlockingQueue queue;
//需求量
int total = 10;
//给手作屋指定货架
Provider (BlockingQueue queue){
this.queue = queue;
}
//手作屋的工作
@Override
public void run() {
//我们就简单看一下制作10个手办的过程吧
for(int i = 0;i<total;i++){
try {
//上货
queue.put(i);
System.out.println("provider:"+i);
} catch (InterruptedException e) {
//log e.printStackTrace();
}
}
}
}
消费者,但凡有货我就买买买。
public class Consumer implements Runnable{
//final修饰的,全世界惟一的货架
private final BlockingQueue queue;
//给消费者指定货架
Consumer (BlockingQueue queue){
this.queue = queue;
}
@Override
public void run(){
//存在即真理,上货就要买。
while(true){
try {
//queue.take()买买买,消费
System.out.println("consumer:"+queue.take());
} catch (InterruptedException e) {
//log e.printStackTrace();
}
}
}
}
好了,我们定义了生产者和消费者两种对象。
他们行为如下:
生产者,每生产一个货物,就会放进队列中;
消费者,每当队列中有一个货物,就会消费掉。
BlockingQueue的put()方法保障了队列满了之后不会继续入队;take()方法保障了队列空了之后不会继续出队的边界情况。
让我们在代码小世界中,启动消费者与生产者的ai,模拟手作屋和死宅的人生吧。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Test {
public static void main(String[] args){
//保障上货货架与购物货架是一个货架。
BlockingQueue queue = new LinkedBlockingQueue();
Thread provider = new Thread(new Provider(queue));
Thread consumer = new Thread(new Consumer(queue));
//手作屋就位
provider.start();
//死宅就位
consumer.start();
}
}
网友评论