title: 生产者消费者模型
tags: 多线程 synchronized 锁 wait() notify()
生产者/消费者模型原理以及代码实现
一、生产者/消费者模型原理
所谓的生产者消费者模型,是通过一个容器来接解决生产者和消费者的强耦合的问题。通俗地将,就是生产者在不断地生产,而消费者在不断地消费,可是生产者不可能一直生产,因为用来装生产者生产的东西的容器容易装满,而此时,生产者就不能够一直去生产,消费者此时就可以从该容器中消费该产品,但是呢,容器中的东西也终会被消耗殆尽的一刻的,在这一刻呢,又需要生产者去生产,这样不断地去重复。这样使用对电脑的内存、cpu资源产生开销太大了。
其实,该容器可以理解为一个阻塞队列,生产者生产的产品不直接给消费者,而是给到阻塞队列,最后才由消费者从该队列消费产品。由整个过程,我们就能总结出,生产者消费者模型就是用来解决这样生产者消费者之间强耦合的,解决了生产和消费的速度不匹配等问题。
二、生产者/消费者模型关注的是以下的点:
①生产者生产的时候消费者不能消费;
②消费者消费的时候生产者不能生产;
③缓冲区空时消费者不能消费;
④缓冲区满时生产者不能生产。
三、生产者/消费者模型的有点主要在于:
①解耦。因为在多了一个缓冲区,所以生产者和消费者之间不能相互直接调用,这样一来,当生产者和消费者的代码发生变化时,都不会对对方产生影响,因此就将生产者和消费者之间的强耦解开了;
②通过平衡生产者和消费者之间的处理能力来提高整体处理数据的速度。如果消费者直接从生产者这里拿数据,如果生产者生产的速度很慢,但是消费者消费的速度很快,那消费者就得占用cpu的时间白白地等待,这样就大大增大了cpu的开销了,浪费了资源了。而有了生产者和消费者模型了,生产者和消费者就成了两个相互独立的个体,生产者只要把它自己生产的东西往缓冲区一丢即可,不必管消费者,消费者亦然,直接冲缓冲区取数据就行,不必管生产者,缓冲去满了就不生产,缓冲区空了就不消费了,这样在消费者和生产者之间就能够到达一个动态的平衡。
四、利用wait()和notify()实现生产者/消费者模型
先建一个仓库类ValueObject类:
package ProduceCustomer1218;
public class ValueObject {
public static String value = "";
}
生产者类:
package ProduceCustomer1218;
public class Producer {
private Object lock;
public Producer(Object lock){
this.lock = lock;
}
public void setValue(){
try{
synchronized(lock){
System.out.println(Thread.currentThread().getName()+"线程开始");
if (!ValueObject.value.equals("")) lock.wait();
String value = System.currentTimeMillis() + "__" + System.nanoTime();
System.out.println("Set的值:" + value);
ValueObject.value = value;
lock.notify();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
消费者类:
package ProduceCustomer1218;
public class Customer {
private Object lock;
public Customer(Object lock){
this.lock = lock;
}
public void getValue(){
try{
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"线程开始");
if(ValueObject.value.equals("")) lock.wait();
System.out.println("Get的值:"+ ValueObject.value);
ValueObject.value = "";
lock.notify();
}
}catch(Exception e){
e.printStackTrace();
}
}
//程序的入口
public static void main(String[] args) {
Object lock = new Object();
Producer producer = new Producer(lock);
Customer customer = new Customer(lock);
Runnable produceRunnable = new Runnable() {
@Override
public void run() {
while(true){
producer.setValue();
}
}
};
Runnable customRunable = new Runnable() {
@Override
public void run() {
while(true){
customer.getValue();
}
}
};
Thread producerThread = new Thread(produceRunnable);
Thread customerThread = new Thread(customRunable);
producerThread.start();
customerThread.start();
}
}
输出的结果为:
从输出的结果上可以看出:
生产数据和消费数据一定是成对出现,生产一个消费一个,满了不生产,空了不消费,达到了平衡生产者和消费者的处理能力了。