SpringBoot定时任务和异步操作

2020-08-03  本文已影响0人  其实是白羊

SpringBoot定时任务和异步操作

日常求赞,感谢老板。

欢迎关注公众号:其实是白羊。干货持续更新中......

image

一、定时任务

在做业务时总会有这样的场景:在特定时间去执行某些逻辑。这其实就是定时任务的应用场景,比如:需要每月一日给用户发上月数据总结等场景。

1.技术

实现定时任务的技术很多

2.注解使用

1)@EnableScheduling

开启定时任务,可标注在启动类或者任何配置类上(能扫描到对象上都可以)

2)@Scheduled

配置具体的任务执行规则,可标注在能被扫描的类的方法上,属性有:

3.cron表达式

定时任务的场景:延迟执行、一定频率执行、指定时间执行

这里的cron表达式即为了描述任务执行的时间规则。cron由6-7个元素组成,他们之间使用空格来分割,以此代表:

除了上面的数字元素值还有下面几个特殊的元素值:

了解了上面的表达式规则就可以写出满足条件的cron表达式了,建议多设计几个场景练习下

4.单线程和多线程执行

如果就按上面的配置写好任务A(fixedRate=2000)和任务B(fixedRate=3000)直接启动执行的话,会存在以下问题:

上面的问题都不能让我们的任务按照各自规定的执行计划去执行,归根到底还是所有的任务都在一个线程里进行,所以做不到异步的并发执行,那这是就可以通过多线程来实现各个任务之间异步的并发执行

这里我们可以使用Spring的@Async注解来实现异步

二、异步

SpringBoot同样支持@Async来实现异步(增加了自动配置可直接使用)

1.注解

1)@EnableAsync

标注在启动类或配置类上,表是开启异步

2)@Async

可标注在类上(能被spring容器扫描到的类上)或方法上

标注在类上则这个类里的方法都被表示为异步

2.异步方法两种返回值

  1. 不需要返回值:void

  2. 需要返回值:

     @Async  
        public Future<String> doTaskOne() throws Exception {
            return new AsyncResult<>("任务一完成");  
        }  
    

3.自动配置

使用@Async来实现异步,其底层还是使用了多线程来进行实现的,那么这个多线程或者线程池是在哪里设置或配置的呢?我们都直到SpringBoot加入了大量的自动配置,我们在spring-boot-autoconfigure包下面可以找到task包下的TaskExecutionAutoConfiguration类中:

@Lazy
@Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,
            AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
@ConditionalOnMissingBean(Executor.class)
//这个注解的意思:当在容器中没有发现Executor这个类则会加载这个bean,可以理解为此处为默认缺省对象
//返回的是一个spring为我们提供的线程池
    public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
        return builder.build();
    }

找到TaskExecutorBuilder:

@Bean
    @ConditionalOnMissingBean
    public TaskExecutorBuilder taskExecutorBuilder() {
        TaskExecutionProperties.Pool pool = this.properties.getPool();
        TaskExecutorBuilder builder = new TaskExecutorBuilder();
        builder = builder.queueCapacity(pool.getQueueCapacity());
        builder = builder.corePoolSize(pool.getCoreSize());
        builder = builder.maxPoolSize(pool.getMaxSize());
        builder = builder.allowCoreThreadTimeOut(pool.isAllowCoreThreadTimeout());
        builder = builder.keepAlive(pool.getKeepAlive());
        builder = builder.threadNamePrefix(this.properties.getThreadNamePrefix());
        builder = builder.customizers(this.taskExecutorCustomizers.orderedStream()::iterator);
        builder = builder.taskDecorator(this.taskDecorator.getIfUnique());
        return builder;
    }

这里的properties是在TaskExecutionProperties加载进来的,默认的参数:

private int queueCapacity = Integer.MAX_VALUE;
private int coreSize = 8; 
private int maxSize = Integer.MAX_VALUE;
private boolean allowCoreThreadTimeout = true;

根据下面可知,也可以从yml/properties文件中自定义配置

@ConfigurationProperties("spring.task.execution")

除了上面的方法我们还可以定义自己的Bean来替换默认缺省Bean,根据@ConditionalOnMissingBean(Executor.class)可知,我们只需要在配置类里加上:

@Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(核心线程数量);
        executor.setMaxPoolSize(最大线程数量);
        executor.setQueueCapacity(任务队列大小);
        executor.initialize();
        return executor;
    }

三、最后

根据上面的介绍,要实现异步的定时任务就可以展开,任务方法上面加上@Async来实现

点个赞啊亲

如果你认为本文对你有帮助,可以「在看/转发/赞/star」,多谢

如果你还发现了更好或不同的想法,还可以在留言区一起探讨下


欢迎关注公众号:「其实是白羊」干货持续更新中......

image image
上一篇 下一篇

猜你喜欢

热点阅读