生产者消费者模式

生产者消费者模式用于解决多线程间处理速度不均衡问题,通过缓冲区实现解耦并提升整体处理效率。该模式有三大优点:支持并发、解耦、应对忙闲不均。在Java中,常通过wait/notify机制实现。
摘要由CSDN通过智能技术生成

生产者消费者模式

为什么要使用生产者/消费者模式

       在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式。


生产者/消费者模型优点
1、解耦。因为多了一个缓冲区,所以生产者和消费者并不直接相互调用,这一点很容易想到,这样生产者和消费者的代码发生变化,都不会对对方产生影响,这样其实就把生产者和消费者之间的强耦合解开,变为了生产者和缓冲区/消费者和缓冲区之间的弱耦合。
2、通过平衡生产者和消费者的处理能力来提高整体处理数据的速度,这是生产者/消费者模型最重要的一个优点。如果消费者直接从生产者这里拿数据,如果生产者生产的速度很慢,但消费者消费的速度很快,那消费者就得占用CPU的时间片白白等在那边。有了生产者/消费者模型,生产者和消费者就是两个独立的并发体,生产者把生产出来的数据往缓冲区一丢就好了,不必管消费者;消费者也是,从缓冲区去拿数据就好了,也不必管生产者,缓冲区满了就不生产,缓冲区空了就不消费,使生产者/消费者的处理能力达到一个

生产者/消费者模式的作用
 - 支持并发 - 解耦 - 支持忙闲不均
 调用wait/notify之类的方法要求必须在当前线程对象内部,例如synchronized方法中

用例说明

//存储多个数据的生产者/消费者模型

public class Basket {
	private Object[] arr;
	
	public Basket() {
		arr=new Object[5];
	}

	public synchronized void produce(Object obj) {
		int pos=-1;
		while (true) {
			pos = indexOfNull();
			if (pos == -1)
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			else break;
		}
		System.out.println(Thread.currentThread()+"生产了一个数据:"+obj);
		arr[pos]=obj;
		this.notifyAll();
	}
	public synchronized void consume() {
		int pos=-1;
		while(true) {
			pos=indexOfNonNull();
			if(pos==-1) {
				try {
					this.wait();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}else
				break;
		}
		System.out.println(Thread.currentThread()+"消费了一个数据:"+arr[pos]);
		arr[pos]=null;
		this.notifyAll();
	}
	
	// 是否有空位置,如果有则返回对应下标,如果没有则返回-1
	private synchronized int indexOfNull() {
		int res = -1;
		for (int i = 0; i < arr.length; i++) {
			Object tmp = arr[i];
			if (tmp == null) {
				res = i;
				break;
			}
		}
		return res;
	}
	// 是否有非空位置,如果有则返回对应下标,如果没有则返回-1
		private synchronized int indexOfNonNull() {
			int res = -1;
			for (int i = 0; i < arr.length; i++) {
				Object tmp = arr[i];
				if (tmp != null) {
					res = i;
					break;
				}
			}
			return res;
		}
}
import java.util.Date;

public class Consumer implements Runnable {
	private Basket resource = null;

	public Consumer(Basket resource) {
		this.resource = resource;
	}

	public void run() {
		for (int i = 0; i < 2000; i++) {
			resource.consume();
		}
	}
}
import java.util.Date;

public class Producer implements Runnable {
	private Basket resource = null;

	public Producer(Basket resource) {
		this.resource = resource;
	}

	public void run() {
		for (int i = 0; i < 20; i++) {
			Object obj = new Date();
			resource.produce(obj);
		}
	}
}
public class Test {
	public static void main(String[] args) {
		Basket resource = new Basket();
		for (int i = 0; i < 10; i++) {
			new Thread(new Producer(resource)).start();
			new Thread(new Consumer(resource)).start();
		}
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值