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

来源:互联网 发布:mac版ps cs6破解补丁 编辑:程序博客网 时间:2024/05/18 11:15

  • 引言
  • 一生产一消费情况
    • 1 生产者Producer
    • 2 消费者Customer
    • 3 main函数
    • 4 运行结果
  • 一生产多消费
    • 1 生产者Producer代码不变
    • 2 消费者Customer
    • 3main方法
    • 4 运行结果
    • 5 修改代码的原因
  • 多生产一消费
    • 1 生产者代码修改两处
    • 2 消费者代码和一生产一消费的消费者代码一样
    • 3main函数代码
  • 多生产多消费
    • 1生产者代码和多生产一消费代码一样
    • 2消费者代码和一生产多消费代码一样
    • 3main代码
    • 4 多生产多消费代码的缺陷
  • 总结

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
原创粉丝点击