定时线程池:ScheduledThreadPoolExecutor

什么是ScheduledThreadPoolExecutor?

ScheduledThreadPoolExecutor是JUC中用于定时任务调用 和周期性任务执行 的核心类。它继承于ThreadPoolExecutor,与普通线程池不同的是,它使用的BlockingQueue是DelayedWorkQueue,这使得它能够按照时间顺序调度任务。

ScheduledThreadPoolExecutor内部原理

ScheduledFutureTask

ScheduledThreadPoolExecutor 将任务封装成 ScheduledFutureTask,然后放入一个特殊的阻塞队列 DelayedWorkQueue。

ScheduledFutureTask是具有返回值的任务, 继承自FutureTask。FutureTask的内部有 一个变量state用来表示任务的状态, 一开始状态为NEW, 所有状态为

java 复制代码
private static final int NEW          = 0; // 初始状态,任务尚未开始或尚未完成
private static final int COMPLETING   = 1; // 正在完成,结果已设置但尚未通知等待线程
private static final int NORMAL       = 2; // 正常完成,任务执行成功并设置了结果
private static final int EXCEPTIONAL  = 3; // 异常完成,任务执行过程中抛出了异常
private static final int CANCELLED    = 4; // 已取消,任务在完成前被取消(未响应中断)
private static final int INTERRUPTING = 5; // 正在中断,任务已被中断但中断操作尚未完成
private static final int INTERRUPTED  = 6; // 已中断,任务已被中断且中断操作已完成

并且ScheduledFutureTask内部还有一个变量period用来表示任务的类型:

  • period == 0:一次性任务(非周期性)。
  • period > 0:scheduleAtFixedRate,固定频率。
  • period < 0:scheduleWithFixedDelay,固定延迟。

ScheduledThreadPoolExecutor方法

构造方法

java 复制代码
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}

其中DelayedWorkQueue是一个无界队列,因此maximumPoolSize=Integer.MAX_VALUE这个参数没有意义。

重要方法

ScheduledThreadPoolExecutor有三个重要的函数

  1. schedule(Runnable/Callable, delay, TimeUnit)
  • 在指定的 delay 时间后,执行一次任务。
  • 返回 ScheduledFuture,可用于取消任务或获取结果。
  1. scheduleAtFixedRate(Runnable, initialDelay, period, TimeUnit)
  • 在 initialDelay 后开始第一次执行,然后每隔 period 时间执行一次。
  • 这里的 period 是指两次任务开始执行的时间间隔。
  • 如果某次任务执行时间超过了 period,下一次执行会立即开始,不会并发执行同一个任务(同一个任务实例不会同时运行两次)。
  • 适合"固定频率"的场景,如每5秒采集一次状态。
  1. scheduleWithFixedDelay(Runnable, initialDelay, delay, TimeUnit)
  • 在 initialDelay 后开始第一次执行,之后在上一次执行完成后,等待 delay 时间再执行下一次。
  • delay 是指前一次执行结束到下一次执行开始的间隔。
  • 适合"固定间隔等待"的场景,如发送完一条消息后等 10 秒再发下一条。
相关推荐
颜进强5 分钟前
23 · NestJs ModuleRef 模块引用:容器递给你的"取货窗口",四个 API 四种语义
前端·后端·ai编程
captain3768 分钟前
Maven
java·后端·idea
hsfxuebao9 分钟前
Loop Engineering 已死? 一文带你了解Graph Engineering
人工智能·后端
liangshanbo121530 分钟前
主系统登录后,子系统怎么实现自动登录?
java·网络·数据库
颜进强1 小时前
22 · NestJs InjectionScopes 注入作用域:默认单例不是偷懒,是最优——以及何时才该打破
前端·后端·ai编程
ShineWinsu1 小时前
对于Redis:缓存的解析
java·redis·缓存·缓存穿透·缓存击穿·缓存雪崩·缓存预热
rannn_1111 小时前
【Java面试题】高频面试题1|Java 后端、MySQL、Redis 与 RAG 面试整理
java·jvm·数据库·后端·面试
写后端的胖头鱼1 小时前
一文详解Spring 事务失效场景
java·spring·事务·transactional·事务传播机制
Q26433650231 小时前
【有源码】基于Spring Boot和Vue的在线考试与交流系统-教育信息化背景下在线考试与交流一体化平台
java·vue.js·spring boot·mysql·spring·毕业设计·课程设计
拖孩1 小时前
一个全程 AI 写的小程序「厨菜记」,上线 20 天跑通流量主,收入几块钱,开心得不行
前端·后端·微信小程序