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

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.lryc.cn/news/2385107.html

相关文章:

  • 零基础设计模式——创建型模式 - 生成器模式
  • MD编辑器推荐【Obsidian】含下载安装和实用教程
  • LLama-Factory 遇到的问题
  • I-CON: A UNIFYING FRAMEWORK FOR REPRESENTATION LEARNING
  • Missashe线代题型总结
  • 蓝桥杯13届 卡牌
  • 安卓开发用到的设计模式(1)创建型模式
  • 【PalladiumZ2 使用专栏 3 -- 信号值的获取与设置 及 memory dump 与 memory load】
  • flutter dart 函数语法
  • 课外活动:大语言模型Claude的技术解析 与 自动化测试框架领域应用实践
  • 线程的一些基本知识
  • 【Python打卡Day30】模块与包的导入@浙大疏锦行
  • 26考研|高等代数:λ-矩阵
  • 我店模式系统开发打造本地生活生态商圈
  • 数据库练习(3)
  • OpenGL ES 基本基本使用、绘制基本2D图形
  • spark调度系统核心组件SparkContext、DAGSchedul、TaskScheduler、Taskset介绍
  • BU9792驱动段式LCD
  • Springboot通过SSE实现实时消息返回
  • SD-WAN技术详解:如何优化网络性能与QoS实现?(附QoS策略、链路聚合、网络架构对比)
  • 力扣-将x减到0的最小操作数
  • Web前端开发: 什么是JavaScript?
  • 三、【数据建模篇】:用 Django Models 构建测试平台核心数据
  • 【JAVA】比较器Comparator与自然排序(28)
  • shp2pgsql 导入 Shp 到 PostGIS 空间数据库
  • word设置如“第xx页 共xx页”格式的页码
  • DL00912-基于自监督深度聚类的高光谱目标检测含数据集
  • PostgreSQL架构
  • 文章记单词 | 第111篇(六级)
  • 在Java中,将Object对象转换为具体实体类对象