当前位置: 首页 > news >正文

深入理解高并发编程 - 深度解析ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor 并实现了 ScheduledExecutorService 接口,这使得它可以同时充当线程池和定时任务调度器。

构造方法

public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}

构造方法接收一个 corePoolSize 参数,它表示线程池中的核心线程数。核心线程是一直保持存活的线程,即使没有任务执行,以便支持定时任务的调度。

构造方法的参数及其含义如下:

corePoolSize:线程池中的核心线程数。这些核心线程会一直保持存活,即使没有任务需要执行。核心线程数决定了线程池的基本能力,可以处理的并发任务数为核心线程数。Integer.MAX_VALUE:线程池的最大线程数。这里设置为整数的最大值,表示线程池没有最大线程数限制。当任务数量超过核心线程数时,新的任务会被排队到队列中等待执行。0:非核心线程的闲置存活时间。对于非核心线程(超过核心线程数的线程),如果没有任务需要执行,它们在闲置一段时间后会被回收。NANOSECONDS:时间单位,表示使用纳秒作为时间单位。new DelayedWorkQueue():构造一个 DelayedWorkQueue 对象作为任务队列。DelayedWorkQueue 是一个延迟队列,用于存储定时任务,根据任务的调度时间进行排序。

在这个构造方法中,ScheduledThreadPoolExecutor 将核心线程数、最大线程数、任务队列等参数传递给其父类 ThreadPoolExecutor 的构造方法,从而创建一个具有定时任务调度能力的线程池。

schedule 方法

ScheduledThreadPoolExecutor 提供了一系列 schedule 方法,用于调度定时任务的执行。这些方法允许指定任务的延迟时间,任务会在延迟时间过后执行一次。以下是 schedule 方法的签名和解析:

schedule(Runnable command, long delay, TimeUnit unit):

这个方法用于调度一个 Runnable 任务,在指定的延迟时间后执行一次。返回一个 ScheduledFuture 对象,可以使用它来取消任务或者获取任务执行的结果。

command:要执行的任务。
delay:延迟时间。
unit:时间单位。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Task executed after delay");
ScheduledFuture<?> future = scheduler.schedule(task, 5, TimeUnit.SECONDS);
<V> schedule(Callable<V> callable, long delay, TimeUnit unit):

这个方法与上一个方法类似,不同之处在于它可以调度一个带有返回值的 Callable 任务。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Callable<String> task = () -> "Task result";
ScheduledFuture<String> future = scheduler.schedule(task, 3, TimeUnit.SECONDS);
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit):

这个方法用于调度一个 Runnable 任务,在初始延迟时间后开始执行,然后每隔一定的时间间隔执行一次。任务的执行时间不考虑,每次任务会尽量在指定的时间间隔后执行。

command:要执行的任务。
initialDelay:初始延迟时间。
period:时间间隔。
unit:时间单位。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Task executed at fixed rate");
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit):

这个方法与上一个方法类似,不同之处在于任务的执行间隔是基于任务完成的时间,而不是固定的时间间隔。任务完成后,会等待一段时间(delay)再执行下一次。

command:要执行的任务。
initialDelay:初始延迟时间。
delay:间隔时间。
unit:时间单位。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Task executed with fixed delay");
ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(task, 2, 3, TimeUnit.SECONDS);

这些 schedule 方法可以方便地调度不同类型的定时任务,从简单的延迟执行到周期性执行,以满足各种需求。

decorateTask 方法

在 ScheduledThreadPoolExecutor 中,decorateTask 方法用于对任务进行修饰,以支持定时任务的调度。它会将普通的 Runnable 或 Callable 任务包装成 ScheduledFutureTask 对象,这样可以将任务调度相关的信息添加到任务中,如延迟时间、调度时间等。以下是 decorateTask 方法的部分实现:

protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) {return task;
}protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task) {return task;
}

这两个方法分别用于对 Runnable 和 Callable 任务进行修饰。它们的作用是将传入的任务(runnable 或 callable)与现有的 RunnableScheduledFuture 任务对象进行合并,从而创建一个新的 RunnableScheduledFuture 对象。

decorateTask 方法默认的实现是将传入的任务不做任何修饰,直接返回原来的任务对象。这是因为大部分情况下,任务并不需要额外的修饰。但是,也可以在自定义的子类中覆盖这个方法,以实现自己的修饰逻辑。

这个方法的存在使得 ScheduledThreadPoolExecutor 可以在任务执行前对任务对象进行一些预处理操作,以满足不同的调度需求。通常情况下,不需要直接调用这个方法,它会在 schedule 方法内部自动调用。

scheduleAtFixedRate 方法

scheduleAtFixedRate 方法用于调度一个任务,在初始延迟时间后开始执行,然后每隔一定的时间间隔执行一次。任务的执行时间不考虑,每次任务会尽量在指定的时间间隔后执行。以下是 scheduleAtFixedRate 方法的签名和解析:

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);

参数说明:

command:要执行的任务,即一个实现了 Runnable 接口的对象。
initialDelay:初始延迟时间,表示从调度开始到第一次执行的时间间隔。
period:任务执行的周期间隔。
unit:时间单位。
返回值:ScheduledFuture 对象,表示任务的调度结果。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);Runnable task = () -> System.out.println("Task executed at fixed rate");// 初始延迟 1 秒,周期间隔 2 秒
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);

在上述示例中,任务 task 首次会在 1 秒后执行,然后每隔 2 秒执行一次。需要注意的是,scheduleAtFixedRate 方法不会考虑任务的执行时间。如果任务的执行时间超过指定的周期间隔,后续任务会尽量在每个周期的开始时执行,但可能会累积延迟。因此,如果任务的执行时间很长,可能会影响后续任务的调度,导致调度的间隔变得不精确。

总之,scheduleAtFixedRate 方法适用于需要以固定的时间间隔调度任务,而不考虑任务的执行时间。

scheduleWithFixedDelay 方法

scheduleWithFixedDelay 方法用于调度一个任务,在初始延迟时间后开始执行,然后每次任务完成后会等待一段时间,再执行下一次。任务的执行间隔是基于任务完成的时间,而不是固定的时间间隔。以下是 scheduleWithFixedDelay 方法的签名和解析:

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);

参数说明:

command:要执行的任务,即一个实现了 Runnable 接口的对象。
initialDelay:初始延迟时间,表示从调度开始到第一次执行的时间间隔。
delay:每次任务执行后的等待时间,即任务完成后等待多长时间再执行下一次。
unit:时间单位。
返回值:ScheduledFuture 对象,表示任务的调度结果。

示例:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);Runnable task = () -> System.out.println("Task executed with fixed delay");// 初始延迟 2 秒,每次任务执行后等待 3 秒再执行
ScheduledFuture<?> future = scheduler.scheduleWithFixedDelay(task, 2, 3, TimeUnit.SECONDS);

在上述示例中,任务 task 首次会在 2 秒后执行,然后每次任务完成后会等待 3 秒,再执行下一次。这个方法适用于需要在任务执行完毕后等待一段时间再进行下一次调度的情况,可以避免任务的执行时间对后续任务的调度造成影响。

需要注意的是,scheduleWithFixedDelay 方法会考虑任务的执行时间,确保每次任务的执行间隔都是基于上一次任务完成的时间。这样可以保证在任何情况下,任务之间的时间间隔都保持相对稳定。

triggerTime 方法

onShutdown 方法用于在线程池关闭时执行特定的清理操作。以下是 onShutdown 方法的签名和解析:

protected void onShutdown() {// 默认的实现为空
}

这个方法是一个钩子方法(hook method),在线程池执行 shutdown 或 shutdownNow 方法时会被调用。默认情况下,onShutdown 方法没有实际的实现,即空方法。但是可以通过继承 ScheduledThreadPoolExecutor 并覆盖 onShutdown 方法,来自定义在线程池关闭时的操作。

在自定义实现中,可以进行一些资源释放、清理工作,或者记录日志等操作,以确保线程池的正常关闭和资源的释放。例如:

class CustomScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {

public CustomScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize);
}@Override
protected void onShutdown() {// 在线程池关闭时执行特定的清理操作System.out.println("CustomThreadPoolExecutor is shutting down...");// 执行其他清理操作...super.onShutdown();
}

}
通过覆盖 onShutdown 方法,可以在线程池关闭时执行自定义的清理逻辑,从而确保应用程序的资源管理和退出行为。

相关文章:

深入理解高并发编程 - 深度解析ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor 并实现了 ScheduledExecutorService 接口&#xff0c;这使得它可以同时充当线程池和定时任务调度器。 构造方法 public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, …...

Android---- 一个完整的小项目(消防app)

前言&#xff1a; 针对不同群体的需求&#xff0c;想着应该拓展写方向。医疗app很受大家喜欢&#xff0c;就打算顺手写个消防app&#xff0c;里面基础框架还是挺简洁 规整的。登陆注册和本地数据库写的便于大家理解。是广大学子的毕设首选啊&#xff01; 此app主要为了传递 消防…...

XXX程序 详细说明

用于记录理解PC程序的程序逻辑 1、程序的作用 根据原作者的说明&#xff08;文件说明.txt&#xff09;&#xff0c;该程序 (PC.py) 的主要作用是提取某一个文件夹中的某个设备 (通过config中的信息看出来是Ag_T_8) 产生的日志文件&#xff0c;然后提取其中某些需要的数据&…...

perl下载与安装教程【工具使用】

Perl是一个高阶程式语言&#xff0c;由 Larry Wall和其他许多人所写&#xff0c;融合了许多语言的特性。它主要是由无所不在的 C语言&#xff0c;其次由 sed、awk&#xff0c;UNIX shell 和至少十数种其他的工具和语言所演化而来。Perl对 process、档案&#xff0c;和文字有很强…...

Chrome谷歌浏览器修改输入框自动填充样式

Chrome谷歌浏览器修改输入框自动填充样式 背景字体 背景 input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #fff inset !important; }字体 input:-internal-autofill-selected {-webkit-text-fill-color: #000 !important; }...

Azure CLI 进行磁盘加密

什么是磁盘加密 磁盘加密是指在Azure中对虚拟机的磁盘进行加密保护的一种机制。它使用Azure Key Vault来保护磁盘上的数据&#xff0c;以防止未经授权的访问和数据泄露。使用磁盘加密&#xff0c;可以保护磁盘上的数据以满足安全和合规性要求。 参考文档&#xff1a;https://l…...

Java“牵手”根据关键词搜索(分类搜索)速卖通商品列表页面数据获取方法,速卖通API实现批量商品数据抓取示例

速卖通商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取速卖通商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问速卖通商城的网页来获取商品详情信息。以下是两种常用方法的介…...

商城-学习整理-高级-消息队列(十七)

目录 一、RabbitMQ简介(消息中间件)1、RabbitMQ简介&#xff1a;2、核心概念1、Message2、Publisher3、Exchange4、Queue5、Binding6、Connection7、Channel8、Consumer9、Virtual Host10、Broker 二、一些概念1、异步处理2、应用解耦3、流量控制5、概述 三、Docker安装RabbitM…...

Android Camere开发入门(1):初识Camera

Android Camere开发入门(1):初识Camera 初步了解 在Android开发中,相机(Camera)是一个常见而重要的功能模块。它允许我们通过设备的摄像头捕捉照片和录制视频,为我们的应用程序增加图像处理和视觉交互的能力。 随着Android系统的不断发展和更新,相机功能也不断改进和增…...

hive表的全关联full join用法

背景&#xff1a;实际开发中需要用到全关联的用法&#xff0c;之前没遇到过&#xff0c;现在记录一下。需求是找到两张表的并集。 全关联的解释如下&#xff1b; 下面建两张表进行测试 test_a表的数据如下 test_b表的数据如下&#xff1b; 写第一个full join 的SQL进行查询…...

PMP串讲

&#xff01;5种冲突解决策略 &#xff01;敏捷3355。 &#xff1f;PMP项目管理132种工具技术合集&#xff1a; 参考2&#xff1a;项目管理的132种工具 - 水之座 ?质量管理,有多少种图&#xff1a; ?风险管理,有多少种图&#xff1a; --参考&#xff1a;PMP相关的十八种…...

最长回文子序列——力扣516

动态规划 int longestPalindromeSubseq(string s){int n=s.length();vector<vector<int>>...

从零实现深度学习框架——Transformer从菜鸟到高手(二)

引言 &#x1f4a1;本文为&#x1f517;[从零实现深度学习框架]系列文章内部限免文章&#xff0c;更多限免文章见 &#x1f517;专栏目录。 本着“凡我不能创造的&#xff0c;我就不能理解”的思想&#xff0c;系列文章会基于纯Python和NumPy从零创建自己的类PyTorch深度学习框…...

docker监控平台FAST OS DOCKER --1

感觉这个是目前好用的中文平台&#xff0c;暂为v1吧 拉取镜像 docker pull wangbinxingkong/fast运行镜像 docker run --name fastos --restart always -p 18091:8081 -p 18092:8082 -e TZ"Asia/Shanghai" -d -v /var/run/docker.sock:/var/run/docker.sock -v /e…...

SpringBoot2.0集成WebSocket

<!-- websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency> 新建配置类 import org.springframework.boot.autoconfigure.condition.Cond…...

Vue的Ajax请求-axios、前后端分离练习

Vue的Ajax请求 axios简介 ​ Axios&#xff0c;是Web数据交互方式&#xff0c;是一个基于promise [5]的网络请求库&#xff0c;作用于node.js和浏览器中&#xff0c;它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在…...

Spring源码深度解析三 (MVC)

书接上回 10.MVC 流程&源码剖析 * 问题1&#xff1a;Spring和SpringMVC整合使用时&#xff0c;会创建一个容器还是两个容器&#xff08;父子容器&#xff1f;&#xff09; * 问题2&#xff1a;DispatcherServlet初始化过程中做了什么&#xff1f; * 问题3&#xff1a;请求…...

API接口漏洞利用及防御

API是不同软件系统之间进行数据交互和通信的一种方式。API接口漏洞指的是在API的设计、开发或实现过程中存在的安全漏洞&#xff0c;可能导致恶意攻击者利用这些漏洞来获取未授权的访问、篡改数据、拒绝服务等恶意行为。 1.API接口漏洞简介 API&#xff08;Application Progr…...

解决Spring mvc + JDK17@Resource无法使用的情况

问题描述 我在使用jdk17进行Spring mvc开发时发现 Resource用不了了。 原因 因为JDK版本升级的改动&#xff0c;在Jdk9~17环境下&#xff0c;搭建Springboot项目&#xff0c;会出现原有Resource&#xff08;javax.annotation.Resource&#xff09;不存在的问题&#xff0c;导…...

页面禁用鼠标右键,禁用F12打开开发者工具!!!

文章目录 问题分析方法一方法二方法二问题 今天在浏览博主文章时发现无法复制页面上的内容,也无法F12打开开发者工具,更用不了鼠标右键,于是上网找了原因并亲测可用 分析 方法一 将 <body> 改成 <body oncontextmenu=self.event.returnValue=false>方法二 …...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...