【并发编程】聊聊定时任务ScheduledThreadPool的实现原理和源码解析

news2025/4/22 9:32:07

ScheduledThreadPoolExecutor 是在线程池的基础上 拓展的定时功能的线程池,主要有四种方式,具体可以看代码,
这里主要描述下

  • scheduleAtFixedRate : 除了第一次执行的时间,后面任务执行的时间 为 time = MAX(任务执行时间,每次等待时间) 取最大值
  • scheduleWithFixedDelay:除了第一次执行的时间,后面任务的时间为 任务执行时间+每次等待时间。
    在这里插入图片描述

使用案例

		// 创建一个定时任务线程池
		ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        
        // 延迟1S后执行
        executor.schedule(() -> {}, 1000, TimeUnit.MILLISECONDS);

		// 立马执行
        executor.execute(() -> {
            System.out.println("execute");
        });

		// 第一次延迟1S,之后每3S执行一次,如果任务时间超过3S,那么等任务执行后执行下一次任务
        executor.scheduleAtFixedRate(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("at"+new Date());
        }, 1000, 3000, TimeUnit.MILLISECONDS);

		// 第一次延迟1S执行。任务执行完成后+3S 执行下一次任务
        executor.scheduleWithFixedDelay(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println("with"+new Date());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        },1000, 3000, TimeUnit.MILLISECONDS);

源码解析

其实主要就是把握ScheduledFutureTask 和 线程池的核心流程的类就可以。

ScheduledFutureTask

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

DelayedWorkQueue

本质是一个二叉树形式的堆结构,会将邻近执行时间的任务排在前面。

schedule 方法分析

整体的流程其实就是 封装定时任务,然后触发延迟执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

delayedExecute

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

ScheduledFutureTask.run方法

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

流程图

这里来简单描述下整体的流程
1.先将任务封装成一个任务 ScheduledFutureTask, 根据线程池状态判断是否执行或者删除任务
2.将任务添加到延迟队列中
3.根据线程池配置 看是否创建线程执行任务。
4.运行的线程不断从延迟队列中获取任务执行。

其实本质就是利用线程池复用机制 + 延迟队列 实现定时任务。

在这里插入图片描述

总结

ScheduledThreadPoolExecutor和ThreadPoolExecutor的区别:

  • ThreadPoolExecutor每次addwoker就会将自己的Task传进新创建的woker中的线程执行,因此woker会第一时间执行当前Task,只有线程数超过了核心线程才会将任务放进队列里
  • ScheduledThreadPoolExecutor是直接入队列,并且创建woker时传到woker的是null,说明woker中的线程刚启动时并没有任务执行,只能通过getTask去队列里取任务,取任务时会判断是否到了执行时间,因此具有了延时执行的特性,并且task执行完了,会将当前任务重新放进堆里,并设置下次执行的时间。

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

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

相关文章

Java-servlet(三)Java-servlet-Web环境搭建(下)详细讲解利用maven和tomcat搭建Java-servlet环境

Java-servlet(三)Java-servlet-Web环境搭建(下)利用maven和tomcat搭建Java-servlet环境 前言一、配置maven阿里镜像二、利用IDEA创建maven文件创建maven文件删除src文件创建新的src模版删除example以及org文件 三、在第二个xml文件…

如何选择DevOps平台?GitHub、GitLab、BitBucket、Jenkins对比与常见问题解答

本文内容来源github.com,由GitHub中国授权合作伙伴-创实信息进行翻译整理。 欢迎通过021-61210910、customershcsinfo.com联系我们,免费试用GitHub企业版。 软件是当今领先企业的核心,而开发者则是软件的核心。GitHub作为一个完整的开发者平台…

react中的fiber和初次渲染

源码中定义了不同类型节点的枚举值 组件类型 文本节点HTML标签节点函数组件类组件等等 src/react/packages/react-reconciler/src/ReactWorkTags.js export const FunctionComponent 0; export const ClassComponent 1; export const IndeterminateComponent 2; // Befo…

闭包+求解候选码+最小函数依赖集

一、闭包 直接上例题 简单明了 A的闭包ABC ABC的闭包ABCD ABCD的闭包ABCDE ABCDE的闭包ABCDEG 等于集合R的全集 所以A的闭包为ABCDEG AB的闭包为ABC 二、候选码 答案: 三、最小函数依赖集 求F的最小函数依赖集 去掉多余的 然后! 化为最简

DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之功能优化,添加表格空状态提示,带插图的空状态,Table7空状态2

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…

Unity Shader 学习15:可交互式雪地流程

本质是 利用顶点变换实现的: 通过一个俯视整个场地的正交摄像机,根据绑定在移动物体身上的粒子系统,来获取物体移动过的位置,记录到一张RenderTexture上作为轨迹图,再通过这张图来对雪地做顶点变换。 1. 由于顶点变换需…

嵌入式开发之串行数据处理

前题 前面几篇文章写了关于嵌入式软件开发时,关于串行数据处理的一些相关内容,有兴趣的可以看看《嵌入式开发:软件架构、驱动开发与串行数据处理》、《嵌入式软件开发之生产关系模型》和《嵌入式开发之Modbus-RTU协议解析》相关的内容。从业十…

Centos的ElasticSearch安装教程

由于我们是用于校园学习,所以最好是关闭防火墙 systemctl stop firewalld systemctl disable firewalld 个人喜欢安装在opt临时目录,大家可以随意 在opt目录下创建一个es-standonely-docker目录 mkdir es-standonely-docker 进入目录编辑yml文件 se…

SyntaxError: Unexpected token ‘xxx‘

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…

Unity自定义区域UI滑动事件

自定义区域UI滑动事件 介绍制作1.创建一个Image2.创建脚本 总结 介绍 一提到滑动事件联想到有太多的插件了比如EastTouchBundle,今天想单纯通过UI去做一个滑动事件而不是基于Box2d或者Box去做滑动事件。 制作 1.创建一个Image 2.创建脚本 using UnityEngine; us…

单链表封装 - 使用JavaScript封装

痛苦就是在蜕变吗 目录 链表:链表的特点:单链表:单链表的封装- JS封装: 单链表的应用:解决回文:解决击鼓传花:十进制进制转换其他进制: 链表: 链表就是一种物理存储单元…

TypeError: Cannot convert object to primitive value

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…

【uniapp】图片添加canvas水印

目录 需求&背景实现地理位置添加水印 ios补充 需求&背景 需求:拍照后给图片添加水印, 水印包含经纬度、用户信息、公司logo等信息。 效果图: 方案:使用canvas添加水印。 具体实现:上传图片组件是项目里现有的&#xff…

贪吃蛇身匀速运动模型

通用运动模型 我们已知斜线为移动的距离 d d d, x x x轴总偏移量为 d x dx dx, y y y轴总偏移量为 d y dy dy,在一帧当中,我们也知道能走的距离为 m d md md。那么作为一般的运动模型,该如何确定我们进行移动的方向呢&…

npm 执行安装报错

Fix the upstream dependency conflict, or retry this command with --force or --legacy-peer-deps to accept an incorrect (and potentially broken) dependency resolution. 原因​ 主要的原因是 npm7 以上的版本,新增了一个对等依赖的特性,在以…

笔记五:C语言编译链接

Faye:孤独让我们与我们所爱的人相处的每个瞬间都无比珍贵,让我们的回忆价值千金。它还驱使你去寻找那些你在我身边找不到的东西。 ---------《寻找天堂》 目录 一、编译和链接的介绍 1.1 程序的翻译环境和执行环境 1.1.1 翻译环境 1.1.2 运行环境 …

【c语言概述、数据类型、运算符与表达式精选题】

c语言概述、数据类型、运算符与表达式精选题 一、易错题1.1🎄 c程序的执行1.2🎄 c程序的基本组成单元1.3🎄 c程序的组成1.4🎄 5种基本类型数据类型长度1.5🎄 C语言关键字1.6🎄 整型常量1.7🎄 合…

200个前卫街头氛围涂鸦艺术水墨颜料手绘笔迹飞溅PNG免扣迭加纹理素材 VANTABLACK TEXTURES

探索 Vantablack 200 纹理包:您获得前卫、高分辨率纹理的首选资源。非常适合旨在为其作品添加原始都市氛围的设计师。这些透明迭加层使用简单,但非常有效,只需单击几下,即可将您的设计从普通变为非凡。准备好用既酷又百搭的质地来…

深度学习模型Transformer核心组件—自注意力机制

第一章:人工智能之不同数据类型及其特点梳理 第二章:自然语言处理(NLP):文本向量化从文字到数字的原理 第三章:循环神经网络RNN:理解 RNN的工作机制与应用场景(附代码) 第四章:循环神经网络RNN、LSTM以及GR…

nature genetics | SCENT:单细胞多模态数据揭示组织特异性增强子基因图谱,并可识别致病等位基因

–https://doi.org/10.1038/s41588-024-01682-1 Tissue-specific enhancer–gene maps from multimodal single-cell data identify causal disease alleles 研究团队和单位 Alkes L. Price–Broad Institute of MIT and Harvard Soumya Raychaudhuri–Harvard Medical S…