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

Java 定时任务 - 从基础到高阶使用 - 从 Timer 到 Quart

在 Java 开发中,定时任务是常见需求,比如定时发送邮件、清理日志、同步数据等。从简单的 Timer 到企业级的 Quartz Scheduler。

基础:使用 Timer 和 TimerTask

Timer 和 TimerTask 是 Java 提供的内置工具,适合简单场景。Timer 负责调度,TimerTask 定义任务逻辑。

示例代码

import java.util.Timer;
import java.util.TimerTask;public class TimerExample {public static void main(String[] args) {Timer timer = new Timer();TimerTask task = new TimerTask() {@Overridepublic void run() {System.out.println("任务执行时间: " + System.currentTimeMillis());}};// 延迟 1 秒后执行,每 2 秒重复执行timer.schedule(task, 1000, 2000);// 10 秒后停止new Timer().schedule(new TimerTask() {@Overridepublic void run() {timer.cancel();System.out.println("Timer 停止");}}, 10000);}
}

代码解释
• 创建 Timer 和 TimerTask:
Timer 是调度器,负责管理任务的执行时间。
TimerTask 是一个抽象类,通过重写 run() 方法定义任务逻辑。
• 调度任务:
schedule(task, delay, period):延迟 delay 毫秒后执行任务,每隔 period 毫秒重复执行。
• 停止 Timer:
使用 timer.cancel() 停止调度器。
优缺点
• 优点:简单易用,无需额外依赖。
• 缺点:单线程执行,任务阻塞会影响后续任务;异常可能导致整个 Timer 终止。

适用场景
轻量级任务,如简单的状态检查或日志清理。

中级:使用 ScheduledExecutorService

ScheduledExecutorService 是 Java 并发包(java.util.concurrent)中的工具,基于线程池,支持多任务并发执行,比 Timer 更现代、更稳定。

示例代码

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledExecutorExample {public static void main(String[] args) {ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);Runnable task = () -> System.out.println("任务执行时间: " + System.currentTimeMillis());// 延迟 1 秒后执行,每 2 秒重复(固定频率)scheduler.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);// 10 秒后停止scheduler.schedule(() -> {scheduler.shutdown();System.out.println("Scheduler 停止");}, 10, TimeUnit.SECONDS);}
}

代码解释
• 创建调度器:
Executors.newScheduledThreadPool(2) 创建一个容量为 2 的线程池,支持并发执行。
• 调度任务:
scheduleAtFixedRate(task, initialDelay, period, unit):延迟 initialDelay 后执行任务,每隔 period 时间单位重复执行。
• 停止调度器:
使用 scheduler.shutdown() 优雅关闭线程池。
• 固定频率 vs 固定延迟:
scheduleAtFixedRate:固定时间间隔执行,不考虑任务耗时。
scheduleWithFixedDelay:任务执行完后,等待固定延迟再执行下一次。

优缺点
• 优点:支持多线程并发,异常不会影响调度器,调度方式灵活。
• 缺点:不支持 cron 表达式,需手动管理线程池。
适用场景
需要并发执行多个定时任务,如批量数据处理、状态监控。

高阶:使用 Spring 的 @Scheduled

在 Spring 项目中,@Scheduled 注解是实现定时任务的首选,简单易用,支持 cron 表达式,适合复杂调度需求。

示例代码

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Configuration
@EnableScheduling
@Component
public class SpringScheduledExample {// 每 5 秒执行一次@Scheduled(fixedRate = 5000)public void fixedRateTask() {System.out.println("固定频率任务: " + System.currentTimeMillis());}// 每 5 秒延迟执行(任务完成后等待 5 秒)@Scheduled(fixedDelay = 5000)public void fixedDelayTask() {System.out.println("固定延迟任务: " + System.currentTimeMillis());}// 使用 cron 表达式,每分钟执行一次@Scheduled(cron = "0 * * * * ?")public void cronTask() {System.out.println("Cron 任务: " + System.currentTimeMillis());}
}

代码解释
• 启用调度:
@EnableScheduling 注解启用 Spring 的定时任务支持。
• 定义任务:
@Scheduled(fixedRate = 5000):每 5 秒执行一次任务。
@Scheduled(fixedDelay = 5000):任务完成后,等待 5 秒再执行下一次。
@Scheduled(cron = “0 * * * * ?”):使用 cron 表达式,每分钟的第 0 秒执行。
• Cron 表达式:
格式:秒 分 时 天 月 星期。

配置线程池(可选)

Spring 默认使用单线程调度器,任务阻塞可能导致延迟。可以通过自定义线程池优化:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@Configuration
public class SchedulerConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(10); // 设置线程池大小scheduler.setThreadNamePrefix("scheduled-task-");return scheduler;}
}

代码解释
• ThreadPoolTaskScheduler:Spring 提供的线程池调度器。
• setPoolSize(10):设置线程池大小为 10,支持并发执行。
• setThreadNamePrefix:设置线程名前缀,便于日志追踪。
优缺点
• 优点:注解驱动,配置简单;支持 cron 表达式;与 Spring 生态无缝集成。
• 缺点:依赖 Spring 框架,分布式场景需额外扩展。
适用场景
Spring 项目的定时任务,如缓存刷新、数据同步。

进阶:使用 Quartz Scheduler

Quartz 是一个功能强大的开源调度框架,适合企业级复杂场景,支持分布式调度、任务持久化和动态管理。

示例代码(Spring 集成 Quartz)

1. 添加依赖(pom.xml)

<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.2</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.3.22</version>
</dependency>

2. 定义 Job

import org.quartz.Job;
import org.quartz.JobExecutionContext;public class MyQuartzJob implements Job {@Overridepublic void execute(JobExecutionContext context) {System.out.println("Quartz Job 执行: " + System.currentTimeMillis());}
}

3. 配置 Quartz

import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;@Configuration
public class QuartzConfig {@Beanpublic JobDetailFactoryBean jobDetail() {JobDetailFactoryBean factory = new JobDetailFactoryBean();factory.setJobClass(MyQuartzJob.class);factory.setDurability(true);return factory;}@Beanpublic CronTriggerFactoryBean trigger(JobDetail jobDetail) {CronTriggerFactoryBean factory = new CronTriggerFactoryBean();factory.setJobDetail(jobDetail);factory.setCronExpression("0/5 * * * * ?"); // 每 5 秒执行return factory;}@Beanpublic SchedulerFactoryBean scheduler(Trigger trigger, JobDetail jobDetail) {SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setTriggers(trigger);factory.setJobDetails(jobDetail);return factory;}
}

代码解释
• Job 定义:
MyQuartzJob 实现 Job 接口,重写 execute 方法定义任务逻辑。
• JobDetail 配置:
JobDetailFactoryBean 用于创建 JobDetail,绑定具体的 Job 类。
setDurability(true):即使没有触发器,Job 也会保留。
• Trigger 配置:
CronTriggerFactoryBean 定义触发器,使用 cron 表达式 0/5 * * * * ?(每 5 秒触发)。
• Scheduler 配置:
SchedulerFactoryBean 整合 Job 和 Trigger,启动调度。
优缺点
• 优点:支持复杂调度、任务持久化、分布式调度;动态管理任务。
• 缺点:配置复杂,学习成本较高。
适用场景
• 企业级应用,如订单处理、报表生成。
• 分布式系统或需要动态调整任务的场景。

结语

选择建议:
• 简单任务:用 Timer 或 ScheduledExecutorService,轻量快速。
• Spring 项目:首选 @Scheduled,简单高效。
• 企业级复杂调度:选择 Quartz 或分布式框架(如 XXL-Job)。
注意事项
• 异常处理:在任务中捕获异常,避免调度器崩溃;记录日志便于排查问题。
• 资源管理:确保线程池或调度器及时关闭,释放资源。
• 性能优化:根据任务量调整线程池大小;对于大数据量任务,考虑分片或异步执行。

http://www.dtcms.com/a/341104.html

相关文章:

  • 数据结构 二叉树 二叉树链式结构的实现
  • 数据分析师常用命令
  • 数据结构中的列表:深度解析数组与链表的实现与抉择
  • PyTorch API 3 - distributed
  • 前后端联合实现文件上传,实现 SQL Server image 类型文件上传
  • 51单片机-驱动LED点阵模块教程
  • SQL-leetcode—3374. 首字母大写 II
  • Docker--安装MySQL、Redis
  • 面试常考的 SQL 窗口函数汇总
  • 【Tech Arch】Apache Pig大数据处理的高效利器
  • 深入理解数据结构:从数组、链表到B树家族
  • 数据结构:利用旋转在AVL树中维持平衡(Inserting in AVL with Rotation)
  • FastAPI初学
  • PyTorch API 1
  • 新能源知识库(81)新能源半实物仿真平台介绍
  • C/C++ Linux系统编程:详解常见的系统调用函数,文件I/O核心:open, close, read, write
  • 【C++】基础:C++11-14-17常用新特性介绍
  • 计算机网络技术-局域网配置(Day.4)
  • 微信小程序授权登录+JWT
  • shell间接引用
  • CVE-2018-12613 漏洞复现
  • 为什么我的UI界面会突然卡顿,失去响应
  • FLASK项目快速构建
  • 用TestComplete打造高效CI/CD测试流程
  • nodejs mongodb基础
  • 【论文阅读】-《SIGN-OPT: A QUERY-EFFICIENT HARD-LABEL ADVERSARIAL ATTACK》
  • Gitea Webhook教程:实现git push后自动部署更新网站 (CI/CD入门)
  • 7.2 Linux:驱动开发——模块机制
  • 7.3 Linux:驱动开发——应用程序和驱动程序的交互
  • imx6ull-驱动开发篇30——Linux 非阻塞IO实验