科普文:JUC系列之Java中7种阻塞队列DelayQueue用法

news2024/9/25 21:23:38

阻塞队列DelayQueue是一种无界阻塞队列,‌用于放置实现了Delayed接口的对象。‌这些对象只能在其到期时才能从队列中取走,‌这种队列是有序的,‌即队头对象的延迟到期时间最长。‌如果没有任何延迟到期的对象,‌那么就不会有任何头元素,‌并且poll将返回null(‌当然,‌这取决于具体的实现,‌有可能抛出异常)‌。‌DelayQueue通常用于解决类似缓存系统的设计、‌定时任务调度、‌订单超时处理等问题。‌

  • 缓存系统的设计:‌可以使用DelayQueue保存缓存元素的有效期。‌使用一个线程循环查询DelayQueue,‌一旦能从DelayQueue中获取元素时,‌表示缓存有效期到了,‌可以删除或者更新缓存。‌
  • 定时任务调度:‌系统需要定时执行的任务可以交给DelayQueue保存,‌然后使用一个线程循环查询DelayQueue,‌一旦获取到任务就开始执行,‌比如每个一段时间发送一封邮件、‌扫描一次日志文件等。‌
  • 订单超时处理:‌在电商系统中,‌用户提交了一个订单,‌就可以把这个订单放进DelayQueue,‌设置超时时间,‌超时后仍然没有支付就取消订单。‌

使用DelayQueue时,‌可以通过offer()方法向队列中添加元素,‌如果队列已满则插入操作会失败并返回false(‌尽管DelayQueue实际上是无界的,‌但理论上存在这种可能性)‌。‌通过take()方法可以从队列中获取并移除头部元素,‌如果队列为空,‌则此方法会阻塞等待直到有元素可用。‌此外,‌DelayQueue还支持超时获取元素的操作,‌即可以设置一个超时时间,‌如果在该时间内队列中没有元素可用,‌则方法会返回。‌

在实现上,‌DelayQueue使用了内部锁和条件变量来处理元素的添加和移除操作。‌当添加元素时,‌如果队列为空或者新元素的延迟时间比当前头部元素的延迟时间要短,‌那么就会将新元素添加到队列中并可能唤醒等待的线程。‌而当移除元素时,‌如果队列为空或者请求的超时时间已经到达,‌那么线程就会被阻塞直到有元素可用或者超时。‌这种机制使得DelayQueue能够支持延迟处理和阻塞等待的功能

DelayQueue属于排序队列,它的特殊之处在于队列的元素必须实现Delayed接口,该接口需要实现compareTo和getDelay方法。

    static class Task implements Delayed{
        @Override
                //比较延时,队列里元素的排序依据
        public int compareTo(Delayed o) {
            return 0;
        }
        
        @Override
                //获取剩余时间
        public long getDelay(TimeUnit unit) {
            return 0;
        }
    }

DelayQueue是一个支持延时操作的无界阻塞队列。列头的元素是最先“到期”的元素,如果队列里面没有元素到期,是不能从列头获取元素的,哪怕有元素也不行。也就是说只有在延迟期满时才能够从队列中去元素。

它主要运用于如下场景:

1.缓存系统的设计:缓存是有一定的时效性的,可以用DelayQueue保存缓存的有效期,然后利用一个线程查询DelayQueue,如果取到元素就证明该缓存已经失效了。
2.定时任务的调度:DelayQueue保存当天将要执行的任务和执行时间,一旦取到元素(任务),就执行该任务。
DelayQueue采用支持优先级的PriorityQueue来实现,但是队列中的元素必须要实现Delayed接口,Delayed接口用来标记那些应该在给定延迟时间之后执行的对象,该接口提供了getDelay()方法返回元素节点的剩余时间。同时,元素也必须要实现compareTo()方法,compareTo()方法需要提供与getDelay()方法一致的排序。

元素进入队列后,先进行排序,然后,只有getDelay也就是剩余时间为0的时候,该元素才有资格被消费者从队列中取出来,所以构造函数一般都有一个时间传入。
具体实例:

package yxxy.c_025;

import java.sql.Time;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class Delayquue {

    public static void main(String[] args) throws Exception {
        BlockingQueue<Task> delayqueue = new DelayQueue<>();
        long now = System.currentTimeMillis();
        delayqueue.put(new Task(now+3000));
        delayqueue.put(new Task(now+4000));
        delayqueue.put(new Task(now+6000));
        delayqueue.put(new Task(now+1000));
        System.out.println(delayqueue);
        
        for(int i=0; i<4; i++) {
            System.out.println(delayqueue.take());
        }
        
    }
    
    static class Task implements Delayed{
        long time = System.currentTimeMillis();
        public Task(long time) {
            this.time = time;
        }
        @Override
        public int compareTo(Delayed o) {
            if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
                return -1;
            else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) 
                return 1;
            else 
                return 0;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(time - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
        }
        @Override
        public String toString() {
            return "" + time;
        }
    }
}

输出结果:

可以看出来,每隔一段时间就会输出一个元素,这个间隔时间就是由构造函数定义的秒数来决定的。

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

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

相关文章

示例:在ML.NET中应用Model Builder模型生成器构建图片对象检测模型

一、目的&#xff1a;ML.NET 是一个开源且跨平台的机器学习框架&#xff0c;专为 .NET 开发人员设计。它允许你在 .NET 应用程序中构建、训练和部署机器学习模型&#xff0c;而无需离开 .NET 生态系统。ML.NET 支持多种机器学习任务&#xff0c;包括分类、回归、聚类、异常检测…

五、栈与队列(2)

五、栈与队列&#xff08;2&#xff09; [150. 逆波兰表达式求值 ](https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/)[239. 滑动窗口最大值 ](https://leetcode.cn/problems/sliding-window-maximum/description/)[347.前 K 个高频元素 ](https:/…

python学习(day1)

1.Python 是大小写敏感的语言。 比如 print 函数名&#xff0c;该函数定义就是全部小写的&#xff0c; 不能写成 Print 或者 PRINT。 2.在Python语言中也会涉及到 对象&#xff0c; 这些对象包含了一定的数据信息。 Python语言中&#xff0c;所有的 数据 都被称之为 对象。 …

Docker 环境下使用 Traefik v3 和 MinIO 快速搭建私有化对象存储服务

上一篇文章中&#xff0c;我们使用 Traefik 新版本完成了本地服务网关的搭建。接下来&#xff0c;来使用 Traefik 的能力&#xff0c;进行一系列相关的基础设施搭建吧。 本篇文章&#xff0c;聊聊 MinIO 的单独使用&#xff0c;以及结合 Traefik 完成私有化 S3 服务的基础搭建…

C语言:qsort详解

在上一篇文章我们大致的了解了回调函数的用法和作用&#xff0c;在这一篇让我们来了解一下在回调函数qsort的使用吧。 一.qsort qsort是一种用来排各种类型数据的函数&#xff0c;利用的是快速排序的方式。说到排序&#xff0c;我们就想到了之前学习的冒泡排序&#xff0c;但…

MySQL数据如何高效实时同步到Elasticsearch?【送源码】

概述 在实际的项目开发与运维过程中&#xff0c;MySQL 常常扮演着业务数据库的核心角色&#xff0c;以其强大的事务处理能力和数据完整性保障&#xff0c;支撑着系统的稳定运行。然而&#xff0c;随着数据量的急剧增长和查询复杂度的不断提升&#xff0c;单一依赖 MySQL 进行高…

文章管理接口——里面有动态SQL编写,在分页查询里

1.实体类和表结构 2. 新增文章分类 接口文档 实现 完整代码放在校验部分 结果&#xff1a; 参数校验&#xff08;Validation自定义&#xff09; 对state的校验&#xff08;已发布|草稿&#xff09;&#xff0c;已有的注解不能满足校验需求&#xff0c;这时就需要自定义校验注解…

Day30 | 62.不同路径 63. 不同路径 II 343.整数拆分 96不同的二叉搜索树

语言 Java 62.不同路径 不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问…

JVM类加载中的双亲委派机制

【1】什么是双亲委派 Java虚拟机对class文件采用的是按需加载的方式&#xff0c;也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时&#xff0c;Java虚拟机采用的是双亲委派模式&#xff0c;即把请求交由父类处理&#xff0c…

【Git企业级开发实战指南①】Git安装、基本操作!

目录 一、Git是什么&#xff1f;1.1特点1.2功能1.3基本概念 二、Git安装2.1Ubuntu下安装2.2Centos下安装Git 三、Git基本操作3.1创建git本地仓库3.2配置Git3.3 工作区&暂存区&版本库3.4 实操案例3.4.1添加文件 3.5 修改文件3.6版本回退3.7查看历史操作日志3.7撤销修改3…

广东省各区县农业产量数据,数据精度至各区县,2020-2023年四年数据可选!

数据名称: 广东省各区县农业产量数据 数据格式: Shpexcel 数据几何类型: 面 数据坐标系: WGS84 数据时间&#xff1a;2020-2023年 数据来源&#xff1a;广东省统计年鉴 数据字段&#xff1a; 序号字段名称字段说明1province省份名称2city城市名称3county区县名称4cou…

【C++深度探索】红黑树的底层实现机制

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;C从入门至进阶 这里将会不定期更新有关C/C的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 前言 红…

VNC未授权访问漏洞

VNC 是虚拟网络控制台Virtual Network Console的英文缩写。它是一款优秀的远程控制工具软件由美国电话电报公司AT&T的欧洲研究实验室开发。VNC是基于 UNXI 和 Linux 的免费开源软件由 VNC Server 和 VNC Viewer 两部分组成。VNC 默认端口号为 5900、5901。VNC 未授权访问漏…

STM32F407移植LVGL(V8.3版本)

一、LVGL简述 1.丰富且强大的模块化图形组件&#xff1a;按钮、图表、列表、滑条、图片等 2.高级图形引擎&#xff1a;动画、抗锯齿、透明度、平滑滚动、图层混合等效果 3.支持多种输入设备&#xff1a;触摸屏、键盘、编码器、按键等 4.配置可裁剪&#xff0c;最低资源占用&am…

latex中Function函数报错

latex写伪码时&#xff0c;发现报错&#xff0c;截图如下&#xff1a; 解决办法&#xff0c;添加宏包&#xff0c;截图如下&#xff1a; \usepackage{algpseudocode}

虚幻引擎 C++ 实现平面阴影

1、平面阴影介绍 平面阴影是一种相对简单的渲染阴影的方式&#xff0c;可以理解为对一个模型渲染两次&#xff0c;一次是渲染模型本身&#xff0c;另一次是渲染模型的投影。渲染投影可以看作是将模型的顶点变换到地面的投影空间再渲染&#xff0c;可以理解为渲染了一个“压扁”…

pytorch学习笔记6 tensor拼接和拆分

cat 合并 dim必须首选相同&#xff08;上例都是3&#xff09;&#xff0c;其次除了合并的dim&#xff08;上例中为dim0&#xff09;外&#xff0c;其它dim的size必须相同&#xff08;dim 1的size是32&#xff0c;dim2的size是8&#xff09;&#xff0c;否则需要手动处理到相同…

vue3 + Spingboot + oracle 通过Base64存储图片

一 、前言 近期在做vue3 Springboot oracle 的工作&#xff0c;有个小功能通过页面导入图片保存到oracle数据库中&#xff0c;本人对前端不是很熟悉&#xff0c;借此记录一下实现方法&#xff1b; 二、前端部分代码 <template><div class"dialog-mian"&…

SQL注入实例(sqli-labs/less-7)

0、初始页面 1、确定闭合字符 确定闭合字符为单引号括号括号 )) ?id1 and 11 ?id1 and 12 ?id1 ?id1)) 2、查看securie_file_priv参数 ?id1)) and upddatexml(1,concat(0x7e,(select secure_file_priv),0x7e),1) -- 3、写入一句话木马 ?id1)) union select null,&q…

SFT、RLHF、DPO、IFT —— LLM 微调的进化之路

TL;DR • SFT、RLHF 和 DPO 都是先估计 LLMs 本身的偏好&#xff0c;再与人类的偏好进行对齐&#xff1b; • SFT 只通过 LLMs 生成的下一个单词进行估计&#xff0c;而 RLHF 和 DPO 通过 LLMs 生成的完整句子进行估计&#xff0c;显然后者的估计会更准确&#xff1b; • 虽然…