java中Queue、BlockingQueue以及DelayQueue的用法

news2024/11/24 16:59:41

java中Queue、BlockingQueue以及DelayQueue的用法

    • 一 Queue 的用法
      • Java中Queue的api
    • 二 BlockingQueue 的用法
      • 阻塞队列的边界
    • 三 DelayQueue使用
      • DelayQueue常见的应用场景

一 Queue 的用法

Queue(队列):其特性是先进先出。只允许在表的一端进行插入,而在表的另一端进行删除。插入叫做入队,删除叫做出队。

Java中Queue的api

  1. int size():获取队列长度;
  2. boolean add(E) / boolean offer(E):添加元素到队尾;
  3. E remove() / E poll():获取队首元素并从队列中删除;
  4. E element() / E peek():获取队首元素但并不从队列中删除。

例子demo:

import java.util.LinkedList;
import java.util.Queue;
 
public class Main {
    public static void main(String[] args) {
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        // 多态   LinkedList  是  Queue 的子类
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
    }
}

// 结果
a
b
c
d
e
===
poll=a
b
c
d
e
===
element=b
b
c
d
e
===
peek=b
b
c
d
e

二 BlockingQueue 的用法

BlockingQueue 继承了 Queue 接口,是一种阻塞队列

何为阻塞队列?

  1. 支持阻塞的插入方法put: 队列满时,队列会阻塞插入元素的线程,直到队列不满。
  2. 支持阻塞的移除方法take: 队列空时,获取元素的线程会等待队列变为非空。

在这里插入图片描述
在这里插入图片描述

阻塞队列的边界

所谓的边界其实就是容量问题。边界分为有界(有固定容量)无界(容量特别大)两种

无界队列意味着里面可以容纳非常多的元素,例如 LinkedBlockingQueue 的上限是 Integer.MAX_VALUE,是非常大的一个数,可以近似认为是无限容量,因为我们几乎无法把这个容量装满。

但是有的阻塞队列是有界的,例如 ArrayBlockingQueue 如果容量满了,也不会扩容,所以一旦满了就无法再往里放数据了。

三 DelayQueue使用

DelayQueue一个延迟队列。在指定时间才能获取队列元素,队列头元素是即将过期的元素。且 DelayQueue实现了BlockingQueue是阻塞队列

我们使用的话,需要实现两个方法:

  1. getDelay(TimeUnit.NANOSECONDS)
  2. compareTo。返回元素在队列中的排序方式,一般根据getDelay来计算

DelayQueue是一个没有边界BlockingQueue实现,加入其中的元素必需实现Delayed接口。

  1. 当生产者线程调用put之类的方法加入元素时,会触发Delayed接口中的compareTo方法进行排序也就是说队列中元素的顺序是按到期时间排序的,而非它们进入队列的顺序。排在队列头部的元素是最早到期的,越往后到期时间越晚。

  2. 消费者线程查看队列头部的元素,注意是查看不是取出。然后调用元素的getDelay方法,如果此方法返回的值小0或者等于0,则消费者线程会从队列中取出此元素,并进行处理如果getDelay方法返回的值大于0,则消费者线程wait返回的时间值后,再从队列头部取出元素,此时元素应该已经到期。

DelayQueue常见的应用场景

  1. 淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单。
  2. 饿了吗订餐通知:下单成功后60s之后给用户发送短信通知。
  3. 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等。

demo: 用户下订单,到指定时间不支付处理订单过期

 
/**
 一:定义延时队列的队列元素
 
 * 延时队列。
 * 每次下订单的时候,把订单数据放入队列。
 * 自定义消费者,消费队列。
 */
public class MyDelayMessage implements Delayed{
 
    /**
     * 默认延迟30秒
     */
    private static final long DELAY_MS = 1000L * 30;
 
    /**
     * 订单id
     */
    private final String orderId;
 
    /**
     * 消息创建的时间戳
     */
    private final long createTime;
 
    /**
     * 过期时间
     */
    private final long expire;
 
    public MyDelayMessage(String orderId){
        this.orderId = orderId;
        this.createTime = System.currentTimeMillis();
        this.expire = this.createTime + DELAY_MS;//计算出过期时长
 
    }
 
    public MyDelayMessage(String orderId,long expireSec){
        this.orderId = orderId;
        this.createTime = System.currentTimeMillis();
        this.expire = this.createTime + expireSec * 1000L;//计算出过期时长
    }
 
    /**
     * 返回延迟时长
     */
    @Override
    public long getDelay(TimeUnit unit) {
        //根据当前时间计算
        return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
 
    /*
      对插入队列的数据进行排序。
    */
    @Override
    public int compareTo(Delayed o) {
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }
 
}
/**
  二:创建延时队列。并插入队列元素或者移除元素

  1. 单例模式创建延时队列
  2. 写插入元素与移除元素的方法
 */
public class MyDelayQueue {
    private static DelayQueue<MyDelayMessage> queue = new DelayQueue<>();
 
    private MyDelayQueue(){}
 
    private static class SingletonHolder{
 
        private  static MyDelayQueue singleton = new MyDelayQueue();
    }
    
    //单例队列
    public static MyDelayQueue getQueue(){
        return SingletonHolder.singleton;
    }
 
 
    public  Boolean  produce(MyDelayMessage message){
        return queue.add(message);
    }
 
    /**
     * 延迟消费队列,取不到的话会阻塞一直到队列有消息再被唤醒。之后再取消息
     */
    public  MyDelayMessage consume() throws InterruptedException {
        return queue.take();
    }
 
 
 
}
    /*
      三:插入队列。

      前端下订单,后端插入队列。
    */
@Controller
@RequestMapping("order")
public class OrderController extends BaseController {
 
    /**
     * 下订单
     */
    @PostMapping()
    @ResponseBody
    public WSResponseVO doOrder(){
        //调用生成订单逻辑,并返回订单id
        String orderId = UUID.randomUUID().toString();
        //此处设置过期时间,10s
        MyDelayQueue.getQueue().produce(new MyDelayMessage(orderId,10));
        return operateSuccess();
    }
 
}
 
/**
 * 四:创建消费者,用于消费队列中的元素
 */
@Component
public class OrderCancelTask implements ApplicationRunner {
 
    /**
     * 在容器启动完成的时候,会执行一个线程。从MyDelayQueue中取消息
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("========开启处理过期订单线程=========");
        new Thread(()->{
            while (true){
                MyDelayMessage msg = null;
                try {
                    msg = MyDelayQueue.getQueue().consume();
                    if(msg != null){
                        //订单过期的业务逻辑。。。。
                        System.out.println("有订单 " + msg.getOrderId() + " 过期");
 
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
 
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/488801.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图像分割】视觉大模型SEEM(Segment Everything Everywhere All at Once)原理解读

文章目录 摘要&#xff08;效果&#xff09;二、前言三、相关工作四、method4.1 多用途4.2 组合性4.3 交互式。4.4 语义感知 五、实验 论文地址&#xff1a;https://arxiv.org/abs/2304.06718 测试代码&#xff1a;https://github.com/UX-Decoder/Segment-Everything-Everywher…

Flask使用Flask-SQLAlchemy对数据库操作详解一(配置、表与表之间一对一、多对一、多对多关系及增删改查参数和代码详细总结)

文章目录 1.先来一个简单的示例2.SQLAlchemy 配置&#xff08;所有的配置都在Flask初始化应用程序之前就执行了&#xff09; 3.声明模型3.1声明模型参数3.2表与表之间的关系&#xff08;详细介绍&#xff09;1.一对一关系2.多对一关系3.多对多关系 1.先来一个简单的示例 from …

【Unity3D小功能】Unity3D中实现轮船在水面上移动效果

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 标题是啥我写啥&#xff0c;大家好&#xff0c;今天给大家带来…

chatgpt帮我写的一个小程序气泡框代码

效果图 这是一个气泡框 .bubble { position: relative; padding: 10px; border-radius: 8px; background-color: #ddd; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); } .triangle { position: absolute; width: 0; height: 0; top: -10px; left: 50%; margin-left: -10px; bor…

vue集成animate.css

vue集成animate.css 一 <transition> 标签的用法二 关于animate.css三 vue集成animate.css使用 一 <transition> 标签的用法 使用<transition></transition>标签包裹要加动画的元素。 标签中添加属性name&#xff0c;表示执行动画的名字&#xff0c;不…

python 网络接口测试(post)

代码&#xff1a; import requests url https://xxx.com/xxx # 注意这里必须以json字符串构造数据 data { "username": "showdoc", "password": "xxx" } headers {content-type: application/json} # 与 get 请求一样…

STC15W104 定时器实现灯的闪烁(定时器原理讲解)

一&#xff1a;STC15W104单片机有几个定时器 STC15W104单片机共有2个定时器&#xff0c;分别为定时器0、定时器2。 二&#xff1a;定时器的作用 定时器是单片机中的一种常用外设&#xff0c;用于在一定时间间隔内产生中断。 定时器通常用于计时、测量时间间隔、生成PWM信号等应…

【MybatisPlus】高级版可视化、可配置 自动生成代码

今天看别人使用了一个更加智能的生成代码工具&#xff0c;可视化、可配置策略&#xff0c;非常方便&#xff0c;配置一次&#xff0c;在哪都可以使用&#xff0c;也不会跟项目藕合下面简单说一下使用方式。 1、介绍mybatis-plus-generator-ui 主要是封装了mybatis-plus-gener…

【深度学习】计算机视觉(13)——模型评价及结果记录

1 Tensorboard怎么解读&#xff1f; 因为意识到tensorboard的使用远不止画个图放个图片那么简单&#xff0c;所以这里总结一些关键知识的笔记。由于时间问题&#xff0c;我先学习目前使用最多的功能&#xff0c;大部分源码都包含summary的具体使用&#xff0c;基本不需要自己修…

【AWS入门】将EC2的系统日志推送到CloudWatch

创建一个 EC2 实例&#xff0c;不附加任何 IAM profile. ※这里注意不要用23年最新版本的镜像&#xff0c;该镜像不支持awslogs 选择旧版镜像可成功安装awslogs 开始创建一个 IAM profile 创建角色&#xff0c;服务选择 EC2, policy 选择 CloudWatchAgentServerPolicy. 切换回…

GPT 学术优化 (ChatGPT Academic)搭建过程(含ChatGLM cuda INT4量化环境和newbing cookie)

文章目录 1、GPT Academic2、chatGPT3、chatGLM4、newbing 1、GPT Academic 项目地址&#xff1a;地址 安装部分 git clone https://github.com/binary-husky/chatgpt_academic.git cd chatgpt_academicconda create -n gptac_venv python3.11 conda activate gptac_venv pyt…

ASEMI代理ADM3202ARUZ-REEL7原装ADI车规级ADM3202ARUZ-REEL7

编辑&#xff1a;ll ASEMI代理ADM3202ARUZ-REEL7原装ADI车规级ADM3202ARUZ-REEL7 型号&#xff1a;ADM3202ARUZ-REEL7 品牌&#xff1a;ADI /亚德诺 封装&#xff1a;TSSOP-16 批号&#xff1a;2023 安装类型&#xff1a;表面贴装型 引脚数量&#xff1a;16 工作温度: …

助力数字轻工发展,企企通亮相第十三届中国轻工业信息化大会

新一代数字技术蓬勃发展&#xff0c;数字经济和实体经济加速融合&#xff0c;数字化不仅仅是生产和管理方式的转变&#xff0c;更是一场创新的革命&#xff0c;只有通过持续创新、不断优化产品内容和服务&#xff0c;才能真正满足客户的需求。 近日&#xff0c;第十三届中国轻工…

想要跳槽涨薪 那你准备拿下 Framework 了吗?

2023这个阶段Android 还行&#xff0c;只是初级开发没有之前那么吃香了&#xff0c;初级市场饱和&#xff0c;但是中高级岗位人才还是比较稀缺。 我们Android程序员与其他程序员一样&#xff0c;每过一年焦虑便加深一点&#xff0c;在近几年越来越差的大环境下更是如此。许多程…

C++好难(2):类和对象(上篇)

okay&#xff0c;从这里开始&#xff0c;就进入c比较难的部分了~啊啊啊&#xff01;&#xff01;&#xff01; (﹃ԅ) 坚持坚持啦 ~ ᵎ(•̀㉨•́)و ̑̑ 【本章目标】 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 5.类的作用域 6.类的实…

情景剧本杀闯关系统

情景剧本杀闯关软件的开发需求通常包括以下几个方面&#xff1a; 剧本设计&#xff1a;开发者需要根据用户需求和市场调研&#xff0c;设计不同主题和难度等级的剧本内容&#xff0c;以及游戏过程中的任务、角色和道具等。 游戏引擎开发&#xff1a;为了实现游戏过程中…

TensoRT量化第四课:PTQ与QAT

目录 PTQ与QAT前言1. TensorRT量化2. PTQ3. QAT4. QAT实战4.1 环境配置4.2 pytorch_quantization简单示例4.3 自动插入QDQ节点 总结 PTQ与QAT 前言 手写AI推出的全新TensorRT模型量化课程&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课程为第四课&am…

Netty基础(一)

1.概述 1.1.原生NIO存在的问题 1>.NIO的类库和API繁杂,使用麻烦: 需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等; 2>.需要具备其他的额外技能: 要熟悉Java多线程编程,因为NIO编程涉及到Reactor模式,你必须对多线程和网络编程非常熟悉,才能…

【数据结构与算法】图——邻接表与邻接矩阵

文章目录 一、图的基本概念二、图的存储结构2.1 邻接矩阵2.2 邻接表2.3 邻接矩阵的实现2.4 邻接表的实现 三、总结 一、图的基本概念 图&#xff08;Graph&#xff09;是由顶点的有穷非空集合和顶点之间边的集合组成&#xff0c;通常表示为&#xff1a;G&#xff08;V,E&#…

【服务器数据恢复】多块磁盘离线导致RAID5崩溃的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某品牌StorageWorks存储设备&#xff0c;8块磁盘组建一组raid5磁盘阵列。存储中2块磁盘掉线导致阵列崩溃&#xff0c;经过检查发现掉线的2块磁盘均存在物理故障。 服务器数据恢复过程&#xff1a; 1、硬件工程师对掉线的两块磁盘进行…