(7)Java多线程之消费者/生产者模式

1. 引言

      在上一篇博客中,我们介绍了第四种线程之间的通信方式:等待通知机制。等待通知机制最典型的例子:消费者/生产者模式。在此篇博客中主要介绍等待通知机制中的:消费者/生产者模式,
      什么是消费者/生产者模式?假设我们要生产一种产品,我们一类线程用于生产产品,另外一类线程用于消费产品。在这个Demo中需要三种类:

  • 产品(这里我们用array数组代替)
  • 生产者
  • 消费者

在消费者/生产者模式中过程介绍

  • 在生产者/消费者模式中,产品的数量为1 (注意产品的数量要么等于0,要么等于1)
  • 对于生产者来说:如果产品的数量为0,那么生产者应该生产产品,并且生产者通知消费者,让消费者消费。如果产品数量等于1,那么生产者应该等待消费者消费,如果消费者不消费,生产者将一直等待下去
  • 对于消费者来说:如果产品的数量等于0,那么消费者应该等待生产者生产,如果产品的数量等译1,那么消费者进行消费,消费完成后应该通知生产者生产商品

消费者/生产者模式一共分为以下几种情况:一生产一消费,一生产多消费,多生产一消费,多生产多消费

2. 一生产一消费情况

2.1 生产者(Producer

import java.util.List;

//生产者
public class Producer {
    // arr是我们的产品
    private List arr;
    // 用于控制等待通知机制的对象锁
    private Object lock;

    public Producer(List arr, Object lock) {
        this.arr = arr;
        this.lock = lock;
    }

    // 用户生产产品的方法
    public void addProduct() throws Exception {
            synchronized (lock) {
                if (arr.size() > 0) {
                    System.out.println("已经拥有了一个产品,陷入等待");
                    lock.wait();
                }
                System.out.println("我要生产产品了");
                arr.add("牛奶");
                lock.notify();

        }
    }

}

2.2 消费者(Customer

import java.util.List;

public class Customer {
    // arr是我们的产品
    private List arr;
    // 用于控制等待通知机制的对象锁
    private Object lock;

    public Customer(List arr, Object lock) {
        this.arr = arr;
        this.lock = lock;
    }

    // 用于消费的方法
    public void csmProduct() throws Exception {
            synchronized (lock) {
                if (arr.size() == 0) {
                    System.out.println("没有产品,等待中");
                    lock.wait();
                }
                System.out.println("消费产品" + arr.get(0));
                arr.remove(0);
                // 通知生产者生产
                lock.notify();

            }

    }

}

2.3 main函数

import java.util.ArrayList;
import java.util.List;

public class app {
    public static void main(String[] args) {
        // 创建我们的产品
        List arr = new ArrayList();
        // 创建我们的锁
        Object lock = new Object();
        // 创建消费者
        final Customer c = new Customer(arr, lock);
        // 创建生产者
        final Producer p = new Producer(arr, lock);
        // 消费者线程
        Runnable ct = new Runnable() {
            public void run() {
                try {
                    while (true) {
                        c.csmProduct();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        };
        // 生产者线程
        Runnable pt = new Runnable() {
            public void run() {
                try {
                    while (true) {
                        p.addProduct();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        // 创建一个生产者
        new Thread(pt).start();
        // 创建一个消费者
        new Thread(ct).start();

    }

}

2.4 运行结果

这里写图片描述

  • 从上面例子可以看出来,我们通过等待通知机制成功实现了一生产一消费的生产者消费模式
  • 注意:线程ct和现成pt都需要获得lock对象锁
  • 注意:一生产一消费代码是可以这样写的,在多生产多消费的代码中就要修改了。

3.一生产多消费

3.1 生产者(Producer)(代码不变)

3.2 消费者(Customer

import java.util.List;

public class Customer {
    // arr是我们的产品
    private List arr;
    // 用于控制等待通知机制的对象锁
    private Object lock;

    public Customer(List arr, Object lock) {
        this.arr = arr;
        this.lock = lock;
    }

    // 用于消费的方法
    public void csmProduct() throws Exception {
        synchronized (lock) {
            while (arr.size() == 0) {
                System.out.println("没有产品,等待中");
                lock.wait();
            }
            System.out.println("消费产品" + arr.get(0));
            arr.remove(0);
            // 通知生产者生产(注意这里代码修改了)
            lock.notifyAll();

        }

    }

}
  • 注意代码修改的两个地方:
  • 一个是判断产品的数量,由以前的if改为了while
  • 一个是唤醒线程由:由notify()改为了notifyAll()

3.3main方法

        //...上面代码和一生产一消费一样
        // 创建一个生产者
        new Thread(pt).start();
        // 创建三个消费者
        new Thread(ct).start();
        new Thread(ct).start();
        new Thread(ct).start();

3.4 运行结果

这里写图片描述

3.5 修改代码的原因

这里写图片描述

4 多生产一消费

4.1 生产者代码(修改两处)

import java.util.List;

//生产者
public class Producer {
    // arr是我们的产品
    private List arr;
    // 用于控制等待通知机制的对象锁
    private Object lock;

    public Producer(List arr, Object lock) {
        this.arr = arr;
        this.lock = lock;
    }

    // 用户生产产品的方法
    public void addProduct() throws Exception {
            synchronized (lock) {
                //修改的第一处
                while (arr.size() > 0) {
                    System.out.println("已经拥有了一个产品,陷入等待");
                    lock.wait();
                }
                System.out.println("我要生产产品了");
                arr.add("牛奶");
                //修改的第二处
                lock.notifyAll();

        }
    }

}
  • 原理和一生产多消费的原理一样,参考上面的原理图

4.2 消费者代码(和一生产一消费的消费者代码一样)

4.3main函数代码

        //......上面的代码和一生产一消费的代码一样
        // 创建三个生产者
        new Thread(pt).start();
        new Thread(pt).start();
        new Thread(pt).start();
        // 创建一个消费者
        new Thread(ct).start();

5.多生产/多消费

5.1生产者代码(和多生产一消费代码一样)

5.2消费者代码(和一生产多消费代码一样)

5.3main代码

        //.....上面代码和一生产一消费一样
        // 创建三个生产者
        new Thread(pt).start();
        new Thread(pt).start();
        new Thread(pt).start();
        // 创建三个消费者
        new Thread(ct).start();
        new Thread(ct).start();
        new Thread(ct).start();

5.4 多生产多消费代码的缺陷

这里写图片描述

6. 总结

在本篇博客中,主要利用等待通知机制实现了消费者生产者模式,其中包括有一生产一消费,多生产一消费,一消费多生产,多生产多消费等情况。注意:上面的例子,产品的数量最多是1。还有注意本篇博客,多生产多消费中代码的缺陷。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值