Java:阻塞队列BlockingQueue与应用场景

目录

阻塞队列

BlockingQueue的常用方法

 生产者消费者应用场景


阻塞队列

        阻塞队列BlockingQueue继承自父类Queue,该队列是线程安全的,可以安全的与多个生产者和消费者线程一起使用。

        与阻塞队列相对的,存在“非阻塞队列”的概念,那么两者在入队和出队时的区别是什么呢?答案如下图所示,

         此外,在jdk1.8的源码中,对BlockingQueue的文档注释信息与简单翻译如下,

    A {@link java.util.Queue} that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
    阻塞队列,当获取元素时,会等待队列变为非空状态,才会返回元素值;当写入元素时,会等待队列变为非满状态时,再将其写入。

        核心思想如下:

                ①阻塞队列在变为空时,继续执行取出队列元素的操作时,会发生阻塞,直到队列中有新的元素被写入时,才停止阻塞,取出元素;

                ②阻塞队列在已满时,继续执行写入元素的操作时,会发生阻塞,直到队列中已有的元素被消费而产生空位时,才停止阻塞,写入元素。

BlockingQueue的常用方法

                BlockingQueue提供了如下的常用方法,但是请注意:并非所有的方法都会产生队列阻塞的效果。

                 其中:阻塞的方法是:put()-添加take()-取出

 生产者消费者应用场景

        阻塞队列的一个经典应用场景就是:生产者、消费者问题

        如下示例代码中,基于BlockingQueue阻塞队列与子类ArrayBlockingQueue有限阻塞队列,分别创建了2个生产者线程、1个消费者线程。2个生产者线程每隔2秒生产一个随机数,供这1个消费者进行消费。

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


//生产者
class Producer implements Runnable{
    private final BlockingQueue blockingQueue;//阻塞队列
    private final Random random = new Random();//随机数生成器

    //构造器
    public Producer(BlockingQueue queue){
        this.blockingQueue = queue;//初始化阻塞队列
    }

    //线程任务
    @Override
    public void run() {
        while (true){
            //添加产品到阻塞队列
            try {
                Thread.sleep(2000);//每隔2秒执行一次生产任务
                System.out.println("生产者产出产品");
                this.blockingQueue.put(this.produce());
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("生产时发生异常");
            }
        }
    }

    //生产方法-生产随机数
    Object produce(){
        return random.nextInt();
    }
}

//消费者
class Consumer implements Runnable{
    //阻塞队列
    private final BlockingQueue blockingQueue;

    //构造器
    public Consumer(BlockingQueue queue){
        this.blockingQueue = queue;
    }

    //执行线程任务
    @Override
    public void run() {
        while (true){
            try {
                this.consume(this.blockingQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("消费时发生异常");
            }
        }
    }

    //消费方法
    public void consume(Object production){
        System.out.println("正在消费产品:"+production);
    }

}


public class BlockingQueue_Apply {
    //properties

    //methods
    public static void main(String[] args) {
        //创建阻塞队列ArrayBlockingQueue-指定容量为10
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(10);
        //创建生产者-2个生产商
        Producer producer = new Producer(blockingQueue);
        Producer producer1 = new Producer(blockingQueue);
        //创建消费者
        Consumer consumer = new Consumer(blockingQueue);

        //生产者线程
        Thread producerThread = new Thread(producer);
        Thread producerThread1 = new Thread(producer1);
        //消费者线程
        Thread consumerThread = new Thread(consumer);

        //启动线程任务
        producerThread.start();
        producerThread1.start();
        consumerThread.start();
    }
}

                 如上图所示,该案例中,会不断执行发生生产者生产、消费者消费的子线程任务,并打印信息。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是席木木啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值