SpringBoot定时任务多线程实现示例

测试Spring Boot定时任务冲突时,使用的线程数量

引入依赖:

Spring Boot 2.6.1

 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
 </dependency>

简单的测试类

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @author Song Jiangtao
 * @date 2021/12/22
 * @description:
 */
@Component
@Slf4j
public class Task {

    @Scheduled(cron="*/2 * * * * ?")
    public void process(){
        log.info("do something");
    }

    @Scheduled(fixedRate = 2000)
    public void currentTime(){
        log.info("做点什么");
    }
}

启动类开启定时任务:@EnableScheduling

测试结果如下:

由结果可见,main线程启动以后和scheduling-1线程跑了两个任务

由此可见,Spring Boot 定时器 默认是 单线程

我们新增两个定时任务来看看这样会有什么后果

@Scheduled(cron="*/2 * * * * ?")
public void process2() throws InterruptedException {
     Thread.sleep(5000L);
     log.info("do something use long time");
 }
 @Scheduled(cron="*/2 * * * * ?")
 public void process3() throws InterruptedException {
     Thread.sleep(10000L);
     log.info("do something use long long time");
 }
2021-12-22 16:30:28.735  INFO 14520 --- [           main] c.e.s.SpringBootScheduledApplication     : Starting SpringBootScheduledApplication using Java 1.8.0_202 on TCZ-D with PID 14520 (D:\code\SpringBootScheduled\target\classes started by Administrator in D:\code\SpringBootScheduled)
2021-12-22 16:30:28.738  INFO 14520 --- [           main] c.e.s.SpringBootScheduledApplication     : No active profile set, falling back to default profiles: default
2021-12-22 16:30:29.315  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:29.318  INFO 14520 --- [           main] c.e.s.SpringBootScheduledApplication     : Started SpringBootScheduledApplication in 0.937 seconds (JVM running for 3.068)
2021-12-22 16:30:30.002  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:30:40.003  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something use long long time
2021-12-22 16:30:45.005  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something use long time
2021-12-22 16:30:45.005  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:45.005  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:30:45.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:45.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:45.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:45.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:45.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:55.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something use long long time
2021-12-22 16:30:55.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:55.006  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:30:55.007  INFO 14520 --- [   scheduling-1] c.e.springbootscheduled.scheduled.Task   : do something

很明显任务会发生错乱,严重时会导致线程阻塞,最后崩溃

解决方法:引入线程池

新增配置类,配置线程池

package com.example.springbootscheduled.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Song Jiangtao
 * @date 2021/12/22
 * @description:
 */
@Configuration
@EnableAsync
public class TaskConfig {

    /**
     * 默认线程数
     */
    private static final int corePoolSize = 10;
    /**
     * 最大线程数
     */
    private static final int maxPoolSize = 100;
    /**
     * 允许线程空闲时间(单位:默认为秒),十秒后就把线程关闭
     */
    private static final int keepAliveTime = 10;
    /**
     * 缓冲队列数
     */
    private static final int queueCapacity = 200;
    /**
     * 线程池名前缀
     */
    private static final String threadNamePrefix = "task-thread-";

    /**
     * bean的名称,默认为 首字小写 方法名
     */
    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor getThread() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(keepAliveTime);
        executor.setKeepAliveSeconds(queueCapacity);
        executor.setThreadNamePrefix(threadNamePrefix);
        //线程池拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

每个定时任务添加注解 @Async("taskExecutor")

@Async("taskExecutor")
@Scheduled(fixedRate = 2000)
public void currentTime(){
    log.info("做点什么");
}

启动测试

2021-12-22 16:41:36.141  INFO 19424 --- [           main] c.e.s.SpringBootScheduledApplication     : Starting SpringBootScheduledApplication using Java 1.8.0_202 on TCZ-D with PID 19424 (D:\code\SpringBootScheduled\target\classes started by Administrator in D:\code\SpringBootScheduled)
2021-12-22 16:41:36.143  INFO 19424 --- [           main] c.e.s.SpringBootScheduledApplication     : No active profile set, falling back to default profiles: default
2021-12-22 16:41:36.991  INFO 19424 --- [           main] c.e.s.SpringBootScheduledApplication     : Started SpringBootScheduledApplication in 1.325 seconds (JVM running for 3.392)
2021-12-22 16:41:37.008  INFO 19424 --- [  task-thread-1] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:38.001  INFO 19424 --- [  task-thread-2] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:41:38.991  INFO 19424 --- [  task-thread-5] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:40.003  INFO 19424 --- [  task-thread-8] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:41:40.991  INFO 19424 --- [  task-thread-9] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:42.001  INFO 19424 --- [ task-thread-10] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:41:42.989  INFO 19424 --- [  task-thread-5] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:43.002  INFO 19424 --- [  task-thread-3] c.e.springbootscheduled.scheduled.Task   : do something use long time
2021-12-22 16:41:44.002  INFO 19424 --- [  task-thread-9] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:41:44.990  INFO 19424 --- [  task-thread-5] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:45.002  INFO 19424 --- [  task-thread-6] c.e.springbootscheduled.scheduled.Task   : do something use long time
2021-12-22 16:41:46.001  INFO 19424 --- [  task-thread-9] c.e.springbootscheduled.scheduled.Task   : do something
2021-12-22 16:41:46.990  INFO 19424 --- [  task-thread-6] c.e.springbootscheduled.scheduled.Task   : 做点什么
2021-12-22 16:41:47.002  INFO 19424 --- [  task-thread-1] c.e.springbootscheduled.scheduled.Task   : do something use long time
2021-12-22 16:41:48.002  INFO 19424 --- [  task-thread-4] c.e.springbootscheduled.scheduled.Task   : do something use long long time

到此这篇关于SpringBoot定时任务多线程实现示例的文章就介绍到这了,更多相关SpringBoot定时任务多线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot2 task scheduler 定时任务调度器四种方式

    使用@EnableScheduling方式 @Component @Configurable @EnableScheduling public class Task1 { private static Log logger = LogFactory.getLog(Task1.class); @Scheduled(cron = "0/2 * * * * * ") public void execute() { logger.info("Task1>>" +

  • SpringBoot实现定时任务的三种方式小结

    目录 定时任务实现的三种方式 使用Timer 使用Spring Task 1.简单的定时任务 2.多线程执行 SpringBoot三种方式实现定时任务 定时任务实现的三种方式 Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行.一般用的较少. ScheduledExecutorService:也jdk自带的一个类:是基于线程池设计的定时任务类,每个调度任

  • SpringBoot定时任务调度与爬虫的配置实现

    SpringTask SpringTask是Spring自主研发的轻量级定时任务工具,相比于Quartz更加简单方便,且不需要引入其他依赖即可使用. SpringTask的配置 在配置类中添加一个@EnableScheduling注解即可开启SpringTask的定时任务 import org.apache.commons.lang3.concurrent.BasicThreadFactory; @Configuration @EnableScheduling @ComponentScan(ba

  • Springboot自带定时任务实现动态配置Cron参数方式

    目录 Springboot自带定时任务实现动态配置Cron参数 SpringBoot定时任务的四种实现方式(主要) spring动态配置cron表达式,不需要停服 SchedulingConfigurer接口实现动态加载cron表达式 Springboot自带定时任务实现动态配置Cron参数 同学们,我今天分享一下SpringBoot动态配置Cron参数.场景是这样子的:后台管理界面对定时任务进行管理,可动态修改执行时间,然后保存入库,每次任务执行前从库里查询时间,以达到动态修改Cron参数的效

  • SpringBoot定时任务多线程实现示例

    测试Spring Boot定时任务冲突时,使用的线程数量 引入依赖: Spring Boot 2.6.1 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> 简单的测试类 import lombok.extern.slf4j.Slf4j; import org.springframework.sc

  • springboot 定时任务@Scheduled实现解析

    这篇文章主要介绍了springboot 定时任务@Scheduled实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.pom.xml中导入必要的依赖: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version&g

  • Springboot定时任务Scheduled重复执行操作

    今天用scheduled写定时任务的时候发现定时任务一秒重复执行一次,而我的cron表达式为 * 0/2 * * * * . 在源码调试的过程中,发现是我的定时任务执行过程太短导致的. 于是我另外写了个简单的定时任务 @Component public class TestJob { @Scheduled(cron = "* 0/2 * * * *") public void test() { System.out.println("测试开始"); System.o

  • 详解SpringBoot定时任务功能

    目录 一 背景 二 动态定时任务调度 三 多节点任务执行问题 四 后记 一 背景 项目中需要一个可以动态新增定时定时任务的功能,现在项目中使用的是xxl-job定时任务调度系统,但是经过一番对xxl-job功能的了解,发现xxl-job对项目动态新增定时任务,动态删除定时任务的支持并不是那么好,所以需要自己手动实现一个定时任务的功能 二 动态定时任务调度 1 技术选择 Timer or ScheduledExecutorService 这两个都能实现定时任务调度,先看下Timer的定时任务调度

  • springboot整合xxl-job的示例代码

    目录 关于xxl-job 调度中心 执行器 关于xxl-job 在我看来,总体可以分为三大块: 调度中心 执行器 配置定时任务 调度中心 简单来讲就是 xxl-job-admin那个模块,配置: 从doc里面取出xxl-job.sql的脚本文件,创建对应的数据库. 进行配置文件的配置,如下图 进行日志存放位置的修改 然后idea打包之后就能当作调度中心运行了 访问地址:ip:port/xxl-job-admin 默认的账号密码:admin/123456 注意:你进去后修改密码,有些浏览器就算你账

  • SpringBoot 定时任务遇到的坑

    前言 springboot已经支持了定时任务Schedule模块,一般情况已经完全能够满足我们的实际需求.今天就记录一下我使用 schedule 时候踩的坑吧. 想要使用定时,我们首先要开启支持,其实就是在启动类上面加个注解就 Ok. @SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(A

  • SpringBoot集成JPA的示例代码

    本文介绍了SpringBoot集成JPA的示例代码,分享给大家,具体如下: 1.创建新的maven项目 2. 添加必须的依赖 <!--springboot的必须依赖--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE

  • 详解Springboot对多线程的支持

    这两天看阿里的JAVA开发手册,到多线程的时候说永远不要用 new Thread()这种方式来使用多线程.确实是这样的,我一直在用线程池,到了springboot才发现他已经给我们提供了很方便的线程池机制. 本博客代码托管在github上https://github.com/gxz0422042... 一.介绍 Spring是通过任务执行器(TaskExecutor)来实现多线程和并发编程,使用ThreadPoolTaskExecutor来创建一个基于线城池的TaskExecutor.在使用线程

  • SpringBoot+MybatisPlus+代码生成器整合示例

    项目目录结构: pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.or

  • Golang Cron 定时任务的实现示例

    开门见山写一个 package main import ( "fmt" "github.com/robfig/cron" "log" "strings" "time" ) func CronTask() { log.Println("******** ******* *******") } func CronTest() { log.Println("Starting Cron

随机推荐