使用阻塞队列实现生产者-消费者模式

 

目录

生产者-消费者问题描述

java中解决该问题的办法有三个

本文从阻塞队列的方面介绍该问题,话不多说,上代码 

运行结果展示


 

生产者-消费者模式是并发编程中的一个经典的问题

生产者-消费者问题描述:
1.生产者和消费者在同一时间段内共用同一个存储空间;
2.生产者往存储空间中添加产品,消费者从存储空间中取走产品;
3.当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。

java中解决该问题的办法有三个:

1.sync,wait,notify

2.lock,await,singal

3.阻塞队列实现

本文从阻塞队列的方面介绍该问题,话不多说,上代码

资源类:

package test;

import org.springframework.util.StringUtils;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Resource {
    //该标记变量标记是否开启 “生产-消费”模式,true表示开启,false表示关闭
    private volatile boolean flag = true;
    //定义变量去计算 生产-消费 物品的个数 需要保证原子性,所以使用该类型变量
    private AtomicInteger atomicInteger = new AtomicInteger();
    //定义阻塞队列 以构造方法传入具体的队列形式
    BlockingQueue<String> blockingQueue = null;

    public Resource(BlockingQueue<String> blockingQueue) {
        this.blockingQueue = blockingQueue;
        System.out.println("***传入的阻塞队列是:" + blockingQueue.getClass().getName());
    }

    //定义生产方法
    public void myProd() throws Exception {
        String data = null;
        boolean retValue;
        while (flag) {
            data = atomicInteger.incrementAndGet() + "";
            retValue = blockingQueue.offer(data, 2L, TimeUnit.SECONDS);
            if (retValue) {
                System.out.println(Thread.currentThread().getName() + "\t" + "插入队列" + data + "成功");
            } else {
                System.out.println(Thread.currentThread().getName() + "\t" + "插入队列" + data + "失败");
            }
            TimeUnit.SECONDS.sleep(1);
        }
        System.out.println(Thread.currentThread().getName() + "\t" + "生产动作结束");
    }

    //定义消费方法
    public void myConsume() throws Exception {
        String result = null;
        while (flag) {
            result = blockingQueue.poll(2L, TimeUnit.SECONDS);
            //说明取出失败,超时之后将退出生产-消费模式
            if (StringUtils.isEmpty(result)) {
                flag = false;
                System.out.println(Thread.currentThread().getName() + "\t" + "超过2s没有取到,退出");
                System.out.println();
                System.out.println();
                return;
            }
            System.out.println(Thread.currentThread().getName() + "\t" + "消费" + result + "成功");
            TimeUnit.SECONDS.sleep(2);
        }
    }

    public void stop() throws Exception {
        this.flag = false;
    }

}

测试类

package test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 使用阻塞队列模拟 生产者-消费者 模式
 * 生产者-消费者问题描述:
 * 1.生产者和消费者在同一时间段内共用同一个存储空间;
 * 2.生产者往存储空间中添加产品,消费者从存储空间中取走产品;
 * 3.当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。
 * 程序业务描述:
 * 1.生产者有序生产,消费者有序消费
 * 2.可以通过变量控制该模式启动或者停止
 * 3.生产者产能不足,消费者消费物品时,如果从队列里取不到物品,等待2s,超时则退出该模式
 * 4.生产者生产太多,消费者消费不完,生产者阻塞。
 * 5.库房内存为10
 */
public class Main {
    public static void main(String[] args) throws Exception {
        //new 一个数组阻塞队列,初始化10
        Resource resource = new Resource(new ArrayBlockingQueue<>(10));
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "生产线程启动");
            try {
                resource.myProd();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "A线程").start();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "消费线程启动");
            System.out.println();
            System.out.println();
            try {
                resource.myConsume();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "B线程").start();
        try {
            TimeUnit.SECONDS.sleep(5L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        resource.stop();
        System.out.println("5s时间到,生产-消费模式退出");
    }
}

运行结果展示:

1.生产者有序生产,消费者有序消费
2.可以通过变量控制该模式启动或者停止

3.生产者产能不足,消费者消费物品时,如果从队列里取不到物品,等待2s,超时则退出该模式

4.通过变量控制该模式停止之后,生产结束,消费者未取到物品,等待2s,超时则退出该模式

4.生产者生产太多,消费者消费不完,生产者阻塞。

注:要想模拟上述所有情况,需要修改某些变量的值,例如库存的数值,生产线程生产物品之后休眠的时间,消费线程消费物品之后休眠的时间

发布了20 篇原创文章 · 获赞 14 · 访问量 8795

猜你喜欢

转载自blog.csdn.net/yemuxiaweiliang/article/details/104128733