生产消费线程型是理解多线程的一个好例子,实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了。
对于此模型,应该明确一下几点:
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
代码:
1生产线程类:
- import java.util.List;
- public class Product implements Runnable {
- private List container = null;
- private int count;
- public Product(List lst) {
- this.container = lst;
- }
- public void run() {
- while (true) {
- synchronized (container) {
- if (container.size() >= MultiThread.MAX) {//如果大于设置的MAX库存,生产者就wait等待
- try {
- container.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- container.add(new Object());
- container.notify();//notify叫醒其他在container上的线程(消费者)
- System.out.println("我生产了" + (++count) + "个");
- }
- }
- }
- }
--
2消费线程:
- import java.util.List;
- public class Consume implements Runnable {
- private List container = null;
- private int count;
- public Consume(List lst) {
- this.container = lst;
- }
- public void run() {
- while (true) {
- synchronized (container) {
- if (container.size() == 0) {//如果容器已经空了,消费者wait等待(生产者)
- try {
- container.wait();// 放弃锁
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- container.remove(0);
- container.notify();//叫醒生产者
- System.out.println("我吃了" + (++count) + "个");
- }
- }
- }
- }
--
3.运行测试:
- import java.util.ArrayList;
- import java.util.List;
- public class MultiThread {
- private List container = new ArrayList();
- public final static int MAX = 3;//最大库存
- public static void main(String args[]) {
- MultiThread m = new MultiThread();
- new Thread(new Consume(m.getContainer())).start();
- new Thread(new Product(m.getContainer())).start();
- }
- public List getContainer() {
- return container;
- }
- public void setContainer(List container) {
- this.container = container;
- }
- }
本例中当发现不能满足生产或者消费条件的时候,调用对象的wait方法,wait方法的作用是释放当前线程的所获得的锁,并调用对象的notify() 方法,通知(唤醒)该对象上其他等待线程,使得其继续执行。这样,整个生产者、消费者线程得以正确的协作执行。
notify() 方法,起到的是一个通知作用,不释放锁,也不获取锁。