栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot @Scheduled注解使用:并发问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot @Scheduled注解使用:并发问题

文章目录
  • 开启定时任务
  • 1. 同一任务的同步执行(下次任务执行将在本次任务执行完毕后的下一次配置时间开始)
  • 2.同一任务的异步执行(下次任务将在下一个配置时间开始,不等待当前任务执行完毕)
  • 3.多任务并发执行(划重点,这是一个坑)
  • 总结

整理引用:https://blog.csdn.net/Demo_Liu/article/details/85335414,
https://blog.csdn.net/hello__ZC/article/details/102455847


开启定时任务

要想使用@Scheduled注解,首先要在启动类上添加注解@EnableScheduling

@SpringBootApplication
@EnableScheduling
public class CsdnfwApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(CsdnfwApplication.class, args);
    }
 
}
1. 同一任务的同步执行(下次任务执行将在本次任务执行完毕后的下一次配置时间开始)
   @Scheduled(cron = "*/30 * * * * ?")
    public void ipWriter() throws InterruptedException {
        for(int i=0;i<20;i++){
            System.out.println("1:"+i);
            Thread.sleep(5000);
        }
    }

SpringBoot 默认就是定时任务同步执行的,只要将@Scheduled添加到需要配置的任务方法上,下次任务执行开始将在本次任务执行完毕后才开始。

2.同一任务的异步执行(下次任务将在下一个配置时间开始,不等待当前任务执行完毕)

开启异步支持

@SpringBootApplication
@EnableScheduling
@EnableAsync  //开启异步支持
public class CsdnfwApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(CsdnfwApplication.class, args);
    }
 
}

需要在方法体上添加@Async注解

    @Async
    @Scheduled(cron = "*/30 * * * * ?")
    public void ipWriter() throws InterruptedException {
        for(int i=0;i<20;i++){
            System.out.println("1:"+i);
            Thread.sleep(5000);
        }
    }

注意:这样做在并发情况下,会无限创建线程。解决方法:https://blog.csdn.net/waitu88/article/details/119783542

3.多任务并发执行(划重点,这是一个坑)

使用SpringBoot配置定时任务的过程中,使用@Scheduled配置了多个定时任务,但是在项目启动的时候每次只会启动一个定时任务,只好搜索一波,直到看到了 ThreadPoolTaskScheduler的源码,才发现默认开启的线程数是 1 ,怪不得每次只能执行一个定时任务,以下是部分源码

public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
    private volatile int poolSize = 1;
    
    public void setPoolSize(int poolSize) {
        Assert.isTrue(poolSize > 0, "'poolSize' must be 1 or higher");
        this.poolSize = poolSize;
        if (this.scheduledExecutor instanceof ScheduledThreadPoolExecutor) {
            ((ScheduledThreadPoolExecutor)this.scheduledExecutor).setCorePoolSize(poolSize);
        }
 
    }
}

可以看到poolSize的默认值是1,那现在就好办了,在启动的时候重新配置一番即可。

创建BeanConfig类,注意,需要在类上添加@Component注解,项目启动的时候类中的@Bean注解才会被扫描到,使配置生效。

package com.liufei.beanConfig;
 
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
 

 
@Component
public class BeanConfig {
 
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(2);//我这里设置的线程数是2,可以根据需求调整
        return taskScheduler;
    }
}

总结
  1. 默认@schedule 线程池默认只有一个线程,多个任务时串行 串行
  2. 配置ThreadPoolTaskScheduler的@schedule 指定线程池中线程数量,多个任务并行 并行
  3. 默认@schedule + @Aysnc 多个任务之间串行,单个任务非阻塞异步执行 串行+异步
  4. 配置ThreadPoolTaskScheduler的@schedule+@Async 多个任务之间并行,单个任务非阻塞异步执行 并行+异步
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/877358.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号