当前位置: 首页 > 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>方法二 …...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...