快捷搜索:  汽车  科技

arrayblockingqueue怎么实现并发?阻塞队列BlockingQueue使用

arrayblockingqueue怎么实现并发?阻塞队列BlockingQueue使用// 创建一个 LinkedBlockingQueue 对象 LinkedBlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue(); // 在不违反容量限制的情况下,可立即将指定元素插入此队列,成功返回 true,当无可用空间时候,返回 IllegalStateException 异常。 linkedBlockingQueue.add("car"); // 在不违反容量限制的情况下,可立即将指定元素插入此队列,成功返回 true,当无可用空间时候,返回 false。 linkedBlockingQueue.offer("car"); // 直接在队列中插入元素,当无可用空间时候,阻塞等待。 linkedBlockingQueue.put("car")

1. 前言

本节带领大家认识第三个常用的 Java 并发容器类之 BlockingQueue。

本节先介绍 BlockingQueue 工具类表达的概念和最基本用法,接着通过一个例子为大家解释 BlockingQueue 工具类的使用场合,然后通过简单的编码实现此场景。

下面我们正式开始介绍吧。

2. 概念解释

BlockingQueue 顾名思义,就是阻塞队列。队列的概念同我们日常生活中的队列一样。在计算机中,队列具有先入先出的特征,不允许插队的情况出现。在 Java 中,BlockingQueue 是一个 interface 而非 class,它有很多实现类,如 ArrayBlockingQueue、LinkedBlockingQueue 等,这些实现类之间主要区别体现在存储结构或元素操作上,但入队和出队操作却是类似的。

概念已经了解了,BlockingQueue 工具类最基本的用法是怎样的呢,我们以 LinkedBlockingQueue 实现类为例说明?看下面。

3. 基本用法

// 创建一个 LinkedBlockingQueue 对象 LinkedBlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue(); // 在不违反容量限制的情况下,可立即将指定元素插入此队列,成功返回 true,当无可用空间时候,返回 IllegalStateException 异常。 linkedBlockingQueue.add("car"); // 在不违反容量限制的情况下,可立即将指定元素插入此队列,成功返回 true,当无可用空间时候,返回 false。 linkedBlockingQueue.offer("car"); // 直接在队列中插入元素,当无可用空间时候,阻塞等待。 linkedBlockingQueue.put("car"); // 将给定元素在给定的时间内设置到队列中,如果设置成功返回 true,否则返回 false,超时后返回 fase。 linkedBlockingQueue.offer("car" 10 Timeunit.SECONDS); // 获取并移除队列头部的元素,无元素时候阻塞等待。 linkedBlockingQueue.take(); // 获取并移除队列头部的元素,无元素时候阻塞等待指定时间。超时后返回 null。 linkedBlockingQueue.poll(10 Timeunit.SECONDS); 代码块预览复制

是不是很简单,那 BlockingQueue 应用在哪些场合比较合适呢?下面我们给出最常用的场景说明。

4. 常用场景

BlockingQueue 首先作为一个队列,可以适用于任何需要队列数据结构的场合,其次其具有阻塞操作的特征,可用于线程间协同操作的场合。日常研发中,生产者消费者模型常常使用 BlockingQueue 实现。我们通过一张图了解其基本逻辑。

arrayblockingqueue怎么实现并发?阻塞队列BlockingQueue使用(1)

我们举一个生活中汽车排队加油的例子说明:每一个加油站台就是一个阻塞队列,汽车依次排队进入,先进入的先出站。当站台满了后继车辆就需要排队等待,当前面的汽车加好油离开(出队)后,后面的汽车进入(入队)开始加油。我们用 LinkedBlockingQueue 工具类实现,请看下面代码。

5. 场景案例

import lombok.SneakyThrows; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; public class BlockingQueueTest { // 创建一个 LinkedBlockingQueue 对象,用于汽车排队 private static LinkedBlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue<>(); // 主线程 public static void main(String[] args) throws InterruptedException { // 汽车 int carNumber = 1; while(carNumber < 5) { new Thread(new Runnable() { @SneakyThrows public void run() { // 模拟用时 Thread.sleep(new Random().nextInt(1000)); // 汽车进站排队等待 linkedBlockingQueue.offer(Thread.currentThread().getName()); System.out.println(Thread.currentThread().getName() ":已经排队进入收费站台,等候收费..."); } } "汽车" carNumber ).start(); } // 收费员 new Thread(new Runnable() { @SneakyThrows public void run() { while(true) { // 模拟用时 Thread.sleep(new Random().nextInt(1000)); // 汽车过收费后出站 String car = linkedBlockingQueue.take(); System.out.println(Thread.currentThread().getName() ":汽车" car "已经收费完毕离开收费站台"); } } } "收费员").start(); // 信息展示 new Thread(new Runnable() { @SneakyThrows public void run() { while(true) { Thread.sleep(1000); // 实时公示当前车流排队情况 int howMany = linkedBlockingQueue.size(); System.out.println(Thread.currentThread().getName() ":当前还" howMany "辆在等候过站"); } } } "大屏").start(); Thread.sleep(1000000); } } 代码块预览复制

运行上面代码,我们观察一下运行结果。

汽车1:已经排队进入收费站台,等候收费... 汽车2:已经排队进入收费站台,等候收费... 汽车4:已经排队进入收费站台,等候收费... 收费员:汽车汽车1已经收费完毕离开收费站台 汽车3:已经排队进入收费站台,等候收费... 大屏:当前还3辆在等候过站 收费员:汽车汽车2已经收费完毕离开收费站台 大屏:当前还2辆在等候过站 收费员:汽车汽车4已经收费完毕离开收费站台 收费员:汽车汽车3已经收费完毕离开收费站台 大屏:当前还0辆在等候过站 代码块预览复制

观察结果,和我们的预期一致。

6. 小结

本节通过一个简单的例子,介绍了 BlockingQueue 接口以及一个具体的实现类 LinkedBlockingQueue 的使用场景和基本用法,其他实现了 BlockingQueue 接口的实现类都类似。希望大家在学习过程中,多思考勤练习,早日掌握之。

猜您喜欢: