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

Spring 定时器和异步线程池 实践指南

  前言:Spring:异步线程池和定时器 原理篇

一、Spring Scheduler

1. 创建一个 SpringBoot项目,在启动类上添加 @EnableScheduling 注解,表示开启定时任务。
2. 创建SchedulerService,在方法上面启用@Scheduled 注解

在方法上使用 @Scheduled 注解表示开启一个定时任务:下面参数单位都是毫秒

  • fixedRate:表示按一定频率来执行定时任务,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。
  • fixedDelay:表示按一定时间间隔来执行定时任务,具体是指本次任务结束到下次任务开始之间的时间间隔。该属性还可以配合initialDelay使用, 定义该任务延迟执行时间。
  • initialDelay:表示首次任务启动的延迟时间。与fixedDelay配合使用。
  • cron:通过 cron 表达式来配置任务执行时间,cron 表达式格式为:[秒] [分] [小时] [日] [月] [周] [年]
package com.example.SchedulerDemo.service;import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;@Service
public class SchedulerService {private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSS");@Scheduled(fixedRate = 2000)public void fixedRateTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedRateTask] run: " + LocalDateTime.now().format(formatter));}@Scheduled(fixedDelay = 2000)public void fixedDelayTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedDelayTask] run: " + LocalDateTime.now().format(formatter));}@Scheduled(initialDelay = 2000, fixedDelay = 2000)public void initialDelayTask() throws InterruptedException {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedDelayTaskWithInitialDelay] run: " + LocalDateTime.now().format(formatter));TimeUnit.SECONDS.sleep(5);}@Scheduled(cron = "0/5 * * * * ?")public void cronTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [cronTask] run: " + LocalDateTime.now().format(formatter));}
}

3. 运行Application,日志如下,可以看到由于单线程执行任务,后续的定时任务被block,等之前的任务执行完才排队执行。

二、 异步线程池——多线程执行任务

1. 创建AsyncThreadPoolConfig配置类,并启用@EnableAsync注解,表示开启异步事件的支持

package com.example.SchedulerDemo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@EnableAsync
@Configuration
public class AsyncThreadPoolConfig {@Bean// 设置为首选,以免被SimpleAsyncTaskExecutor替代@Primarypublic ThreadPoolTaskExecutor initialize() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数(长期保持的最小线程数量,即使这些线程处于空闲状态也不会被回收)executor.setCorePoolSize(5);// 设置最大线程数executor.setMaxPoolSize(10);// 设置队列容量executor.setQueueCapacity(10);// 设置线程名称前缀executor.setThreadNamePrefix("MyThread-");// 用于控制线程池在关闭时是否等待正在执行的任务完成executor.setWaitForTasksToCompleteOnShutdown(true);// 初始化,必须executor.initialize();return executor;}}

2. 在定时任务的类或者方法上添加 @Async 注解。

package com.example.SchedulerDemo.service;import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;@Service
public class SchedulerService {private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSS");@Async@Scheduled(fixedRate = 2000)public void fixedRateTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedRateTask] run: " + LocalDateTime.now().format(formatter));}@Async@Scheduled(fixedDelay = 2000)public void fixedDelayTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedDelayTask] run: " + LocalDateTime.now().format(formatter));}@Async@Scheduled(initialDelay = 2000, fixedDelay = 2000)public void initialDelayTask() throws InterruptedException {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [fixedDelayTaskWithInitialDelay] run: " + LocalDateTime.now().format(formatter));TimeUnit.SECONDS.sleep(5);}@Scheduled(cron = "0/5 * * * * ?")public void cronTask() {System.out.println("[" + Thread.currentThread().getName() + "]" + " -> [cronTask] run: " + LocalDateTime.now().format(formatter));}
}

3. 重新运行Application,日志如下,可以看到除了cornTask,其他三个任务配置到了异步线程池中,观察fixedRateTask,可以看到是间隔两秒的。

http://www.xdnf.cn/news/574273.html

相关文章:

  • COMP3023 Design and Analysis of Algorithms
  • ./build/mkfs.jffs2: Command not found
  • 车载诊断架构 --- LIN 节点 ECU 故障设计原则
  • C++继承:从生活实例谈面向对象的精髓
  • 零基础设计模式——创建型模式 - 生成器模式
  • 时源芯微|六大步骤解决EMC问题
  • RAG系统的现实困境与突破:数据泥潭到知识自由
  • QT的自定义控件
  • 【题解-洛谷】B4302 [蓝桥杯青少年组省赛 2024] 出现奇数次的数
  • 数据库——redis
  • 测试--自动化测试概念
  • java21
  • BISS0001:高性能热释电红外感应IC的详细介绍
  • 学习STC51单片机10(芯片为STC89C52RC)
  • 近场探头阵列技术解析
  • (eNSP)主备接口备份配置
  • BitsAndBytesConfig参数描述
  • redisson-spring-boot-starter 版本选择
  • MySQL备份恢复:数据安全的终极指南
  • 基于Matlab建立不同信道模型
  • 苍穹外卖05 Redis常用命令在Java中操作Redis_Spring Data Redis使用方式店铺营业状态设置
  • 本特利内华达125768-01 RIM i/o模块规范
  • ESP.wdtFeed();的作用与功能,以及使用方法
  • 「AR智慧应急」新时代:当AR眼镜遇上智能监控,打造立体化应急指挥系统
  • AskTable 集成 Databend:结构化数据的 AI 查询新体验
  • 项目自启动文件配置
  • quickbi实现关联度分析(复刻PowerBI展示)
  • 【深度学习:理论篇】--Pytorch之nn.Module详解
  • 嵌入式开发学习日志(linux系统编程--文件读写函数(2))Day25
  • 算法——数组代码