关于延迟任务线程池,Java提供的ScheduledThreadPoolExecutor,Spring提供的ThreadPoolTaskScheduler

今天讲解定时任务、延迟任务的线程池使用方式:
1、从 java 角度
2、从 Spring 框架角度

Java提供:ScheduledExecutorService接口(创建延迟任务线程池)

这个接口继承 ExecutorService 接口。

① 用法1:

ScheduledThreadPoolExecutor 类 是 ScheduledExecutorService 接口的实现类,属于 java 并发包。它允许你设置一个固定数量的核心线程池,并调度任务在某个延迟时间后执行,或以固定的频率重复执行任务。

return new ScheduledThreadPoolExecutor(
    5,         // 核心线程池大小
    new BasicThreadFactory.Builder()                // 自定义线程工厂
        .namingPattern("schedule-pool-%d")          // 线程的命名模式
        .daemon(true)                               // 线程设为守护线程
        .build(),
    new ThreadPoolExecutor.CallerRunsPolicy()       // 任务拒绝策略
)
{
   
   
        @Override
        protected void afterExecute(Runnable r, Throwable t
<think>我们正在讨论的是Spring框架中的ThreadPoolTaskScheduler。这是一个用于任务调度的类,它构建在JavaScheduledThreadPoolExecutor之上,提供了更丰富的功能,特别是与Spring的集成。1.功能概述:ThreadPoolTaskSchedulerSpring框架中用于任务调度的类,它实现了TaskScheduler接口。它内部使用了一个ScheduledThreadPoolExecutor来执行任务,支持以下功能:-定时执行任务(一次或多次)-支持cron表达式-支持固定速率(fixedrate)和固定延迟(fixeddelay)的任务-可以配置线程池的大小(核心线程数)-与Spring的生命周期管理集成(实现了InitializingBean和DisposableBean)2.配置参数:-poolSize:线程池的大小,默认是1。-threadNamePrefix:线程名前缀,默认是"task-scheduler-"。-errorHandler:用于处理任务执行过程中抛出的异常。-removeOnCancelPolicy:如果设置为true,当任务被取消时,立即从工作队列中移除,默认是false。3.使用方式:通常,我们可以通过XML配置或者Java配置来定义ThreadPoolTaskScheduler的bean。示例(Java配置):```java@BeanpublicThreadPoolTaskSchedulertaskScheduler(){ThreadPoolTaskSchedulerscheduler=newThreadPoolTaskScheduler();scheduler.setPoolSize(10);scheduler.setThreadNamePrefix("task-scheduler-");scheduler.setAwaitTerminationSeconds(60);scheduler.setWaitForTasksToCompleteOnShutdown(true);scheduler.setErrorHandler(t->{//自定义错误处理逻辑System.err.println("Taskexecutionerror:"+t.getMessage());});scheduler.setRemoveOnCancelPolicy(true);returnscheduler;}```4.使用示例:我们可以使用这个调度器来安排任务。示例:安排一个固定速率的任务(每5秒执行一次)```java@AutowiredprivateThreadPoolTaskSchedulertaskScheduler;//启动一个任务publicvoidscheduleTask(){taskScheduler.scheduleAtFixedRate(()->{//任务逻辑System.out.println("Fixedratetask-"+System.currentTimeMillis());},5000);//每5秒执行一次}//使用cron表达式publicvoidscheduleCronTask(){taskScheduler.schedule(()->{//任务逻辑System.out.println("Crontask-"+System.currentTimeMillis());},newCronTrigger("009**?"));//每天早上9点执行}//安排一个固定延迟任务(上一次任务执行完成后,延迟5秒再执行下一次)publicvoidscheduleFixedDelayTask(){taskScheduler.scheduleWithFixedDelay(()->{//任务逻辑System.out.println("Fixeddelaytask-"+System.currentTimeMillis());},5000);}```5.关闭调度器:由于ThreadPoolTaskScheduler实现了DisposableBean,在Spring容器关闭时,它会自动关闭线程池。但是,我们可以配置它等待正在执行的任务完成(通过setWaitForTasksToCompleteOnShutdown(true)),并设置一个等待的最大时间(setAwaitTerminationSeconds)。6.注意事项:-如果任务执行时间过长,可能会影响其他任务的按时执行,特别是当线程池大小设置为1时(所有任务都在同一个线程中执行)。-任务抛出的异常如果不处理,默认会被记录到日志中。我们可以通过设置ErrorHandler来自定义异常处理。7.与@Scheduled注解的关系:在Spring中,我们通常使用@Scheduled注解来标记一个方法为定时任务。为了支持这个注解,我们需要配置一个TaskScheduler(如ThreadPoolTaskScheduler)或使用默认的。当我们使用@EnableScheduling时,如果上下文中没有TaskScheduler的bean,Spring会默认创建一个单线程的ThreadPoolTaskScheduler。因此,如果我们的定时任务比较多,为了避免任务之间相互等待,我们应该配置一个适当大小的线程池。代码示例:使用ThreadPoolTaskScheduler进行任务调度(完整的SpringBoot示例)```javaimportorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.TaskScheduler;importorg.springframework.scheduling.annotation.EnableScheduling;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;importorg.springframework.stereotype.Component;@Configuration@EnableSchedulingpublicclassAppConfig{@BeanpublicTaskSchedulertaskScheduler(){ThreadPoolTaskSchedulerscheduler=newThreadPoolTaskScheduler();scheduler.setPoolSize(10);scheduler.setThreadNamePrefix("scheduled-task-pool-");scheduler.initialize();returnscheduler;}}@ComponentclassMyScheduledTasks{@Scheduled(fixedRate=1000)//每1秒执行一次publicvoidtaskWithFixedRate(){System.out.println("Fixedratetask:"+System.currentTimeMillis());}@Scheduled(cron="0/2****?")//每2秒执行一次,使用cron表达式publicvoidtaskWithCron(){System.out.println("Crontask:"+System.currentTimeMillis());}}```在上面的例子中,我们配置了一个ThreadPoolTaskScheduler作为任务调度器,并设置了10个线程。然后,我们通过@Scheduled注解定义了两个定时任务。由于有线程池,这两个任务会被不同的线程执行,不会互相阻塞。§§相关问题§§:1.ThreadPoolTaskScheduler和ThreadPoolTaskExecutor有什么区别?2.在Spring中,如何动态地添加和取消定时任务?3.ThreadPoolTaskScheduler线程池配置多少合适?4.如何优雅地关闭ThreadPoolTaskScheduler,以确保所有任务都已完成?</think> ### ThreadPoolTaskScheduler 详解 `ThreadPoolTaskScheduler` 是 Spring Framework 提供的一个任务调度器实现,基于 Java 的 `ScheduledThreadPoolExecutor` 构建,用于处理周期性或延迟执行的任务。它扩展了 `TaskScheduler` 接口,提供线程池管理和任务调度功能。 #### 核心特性: 1. **线程池管理**:维护固定数量的线程执行任务 2. **任务调度**:支持一次性、固定延迟和固定频率任务 3. **Spring 集成**:与 Spring 生命周期管理无缝集成 4. **错误处理**:支持自定义错误处理器 5. **可配置性**:线程名前缀、关闭策略等均可配置 #### 基本使用示例: ```java import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; import java.time.Duration; import java.util.Date; public class SchedulerExample { public static void main(String[] args) throws InterruptedException { // 1. 创建任务调度器 ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(5); // 设置线程池大小 scheduler.setThreadNamePrefix("scheduler-"); // 线程名前缀 scheduler.initialize(); // 必须初始化 // 2. 添加任务 // 一次性延迟任务 scheduler.schedule( () -> System.out.println("One-time task executed at " + new Date()), new Date(System.currentTimeMillis() + 2000) // 2秒后执行 ); // 固定频率任务(每隔1秒执行) scheduler.scheduleAtFixedRate( () -> System.out.println("Fixed-rate task: " + new Date()), 1000 ); // 固定延迟任务(上次结束到下次开始间隔2秒) scheduler.scheduleWithFixedDelay( () -> System.out.println("Fixed-delay task: " + new Date()), 2000 ); // 使用cron表达式(每5秒执行) scheduler.schedule( () -> System.out.println("CRON task: " + new Date()), new CronTrigger("0/5 * * * * ?") ); // 3. 优雅关闭(实际应用中应在Spring容器关闭时自动触发) Thread.sleep(15000); scheduler.shutdown(); } } ``` #### 代码解释: 1. **初始化**: - `setPoolSize()`:设置核心线程数 - `setThreadNamePrefix()`:定义线程名称前缀(方便调试) - `initialize()`:**必须调用**,启动底层线程池 2. **任务类型**: - `schedule(Runnable, Date)`:指定时间执行一次的延迟任务 - `scheduleAtFixedRate()`:固定频率执行(即使前次任务未完成) - `scheduleWithFixedDelay()`:固定延迟执行(等待前次任务完成) - `schedule(Runnable, Trigger)`:使用CronTrigger定义复杂调度 3. **配置参数详解**: ```java scheduler.setAwaitTerminationSeconds(30); // 关闭时等待任务完成的时间 scheduler.setWaitForTasksToCompleteOnShutdown(true); // 关闭时等待正在执行的任务 scheduler.setErrorHandler(ex -> { // 自定义错误处理 System.err.println("Task failed: " + ex.getMessage()); }); scheduler.setRemoveOnCancelPolicy(true); // 立即移除取消的任务 ``` #### Spring Boot 整合示例: 在Spring Boot应用中,通过配置类定义Bean: ```java @Configuration @EnableScheduling public class SchedulerConfig { @Bean public ThreadPoolTaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); scheduler.setThreadNamePrefix("app-scheduler-"); scheduler.setAwaitTerminationSeconds(60); scheduler.setWaitForTasksToCompleteOnShutdown(true); return scheduler; } } ``` #### 最佳实践: 1. **线程池大小**:根据任务类型(I/O或CPU密集型)合理配置 2. **优雅关闭**:确保应用关闭时正确处理未完成任务 3. **异常处理**:实现`ErrorHandler`处理未捕获异常 4. **资源清理**:对长时间运行任务添加超时机制 5. **监控**:集成Micrometer暴露线程池指标 #### 与 Timer/TimerTask 对比: | 特性 | ThreadPoolTaskScheduler | Timer | |--------------------|-------------------------------|-------------------| | 线程模型 | 线程池(多线程) | 单线程 | | 任务隔离 | ⭐️⭐️⭐️⭐️⭐️(任务互不影响) | ⭐️(一个异常终止所有任务) | | 调度精度 | ⭐️⭐️⭐️⭐️(毫秒级) | ⭐️⭐️(受系统时钟影响大) | | Spring 集成 | ⭐️⭐️⭐️⭐️⭐️ | ⚠️(需手动集成) | | 复杂调度支持 | ⭐️⭐️⭐️⭐️⭐️(Cron表达式) | ⚠️(有限支持) |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小学鸡!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值