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

SpringBoot项目多线程实现定时任务-只需要三步

众所周知,项目中需要使用定时任务发布的需求时非常常见的,例如:数据同步,清理垃圾文件,清理过期用户等需求,可能需要我们定时去清理数据。

但是我们如果集成xxl-job,Quartz,spring task等定时任务框架,但是我们如果只是针对某些小需求进行定时任务,完全用不到这样调度框架,Spring Boot框架中集成了@Schedule定时任务。

在我们使用@Schedule注解的时候,需要注意的时,这是一个单线程的定时任务,也就是说当我们在同一时间进行执行多个任务的时候,可能会出现第二个任务无法执行(不是绝对的)、任务执行顺序也不一样(有可能第一个任务先执行,也有可能是第二个任务先执行)。

所以在这里我们要想到使用多线程的方式。

第一步:pom文件修改

在我们创建完成springboot项目后,其实pom文件无需导入其他的依赖了,因为spring-boot-starter这个依赖中了。

第二步:配置ScheduleConfig

package com.example.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;@Configuration
@EnableScheduling
@EnableAsync
public class SchedulingConfig {private final int corePoolSize=2;private final int maxPoolSize=10;private final int queueCapacity=25;private final String namePrefix="AsyncTask-";/*** 自定义线程池配置类。* 不要命名为 taskScheduler,与spring框架的bean重名。* @return*/@Bean(name = "asyncServiceExecutor")public Executor asyncServiceExecutor() {//阿里巴巴编程规范:线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。//SpringBoot项目,可使用Spring提供的对 ThreadPoolExecutor 封装的线程池 ThreadPoolTaskExecutor:ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//        ThreadPoolTaskExecutor executor = new MyThreadPoolTaskExecutor();//自定义ThreadPoolTaskExecutor,会打印线程池情况//配置核心线程数executor.setCorePoolSize(corePoolSize);//配置最大线程数executor.setMaxPoolSize(maxPoolSize);//配置队列大小executor.setQueueCapacity(queueCapacity);//配置线程池中的线程的名称前缀executor.setThreadNamePrefix(namePrefix);// rejection-policy:当pool已经达到max size的时候,如何处理新任务//     1、CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行。//        "该策略既不会抛弃任务,也不会抛出异常,而是将任务回推到调用者。"顾名思义,在饱和的情况下,调用者会执行该任务(而不是由多线程执行)//     2、AbortPolicy:拒绝策略,直接拒绝抛出异常//     3、。。。executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//执行初始化executor.initialize();return executor;}
}

第三步:编写定时任务业务层代码

package com.example.demo.task;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import javax.xml.crypto.Data;
import java.util.concurrent.Executor;@Component
public class BusinessTaskScheduler {@Scheduled(cron = "0 0/1 * * * ?")@Async("asyncServiceExecutor")public void TelecomBusinessTask() {// 业务逻辑代码try {System.out.println("任务1执行时间:"+System.currentTimeMillis());for (int i = 0; i < 6; i++) {System.out.println("执行任务的线程名称: " + Thread.currentThread().getName()+"-----任务1");}} catch (Exception e) {throw new RuntimeException("获取定时任务调用失败!"+e);}}@Scheduled(cron = "0 0/1 * * * ?")@Async("asyncServiceExecutor")public void MobileBeiXiangTask() {try {System.out.println("任务2执行时间:"+System.currentTimeMillis());for (int i = 0; i < 6; i++) {System.out.println("执行任务的线程名称: " + Thread.currentThread().getName()+"-----任务2");}} catch (Exception e) {throw new RuntimeException("获取定时任务调用失败!"+e);}}}

测试结果

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 通过Python绘制不同数据类型适合的可视化图表
  • CSS文本属性与字体
  • 秋招力扣Hot100刷题总结——堆
  • Java和C#哪个更适合大型项目?
  • 17 深入理解 C 语言 main 函数:返回值意义、命令行参数接收、跨环境差异及CMD乱码解决
  • anaconda的power shell和prompt有什么区别?
  • 【TCP】核心机制:滑动窗口、流量控制和拥塞控制
  • ubuntu install Miniconda3(轻量级conda)
  • Using Azure openAI key rotation automation
  • 大数据毕业设计开题报告100例
  • Kafka快速入门:Kafka驱动JavaApi的使用
  • docker容器数据卷、数据卷基本案例
  • WebSocket、Socket和Netty的关系
  • Ubuntu下torch.cuda.is_available() 返回 False情况
  • 2-75 基于matlab的多尺度小波核svm预测
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 07.Android之多媒体问题
  • 30秒的PHP代码片段(1)数组 - Array
  • git 常用命令
  • IndexedDB
  • Java|序列化异常StreamCorruptedException的解决方法
  • JavaScript设计模式之工厂模式
  • JAVA之继承和多态
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Solarized Scheme
  • storm drpc实例
  • tab.js分享及浏览器兼容性问题汇总
  • vue 配置sass、scss全局变量
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 翻译:Hystrix - How To Use
  • 入门到放弃node系列之Hello Word篇
  • 思否第一天
  • 微服务核心架构梳理
  • kubernetes资源对象--ingress
  • ​Linux·i2c驱动架构​
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #13 yum、编译安装与sed命令的使用
  • #数据结构 笔记一
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (2)STM32单片机上位机
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (三)终结任务
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (十)Flink Table API 和 SQL 基本概念
  • (算法)大数的进制转换
  • (一)appium-desktop定位元素原理
  • (转) 深度模型优化性能 调参
  • .FileZilla的使用和主动模式被动模式介绍
  • .gitignore文件设置了忽略但不生效
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core 将实体类转换为 SQL(ORM 映射)