Spring定时任务@Scheduled使用的那些坑

@Scheduled使用多线程方式

  • 前言
  • 一、使用的那些坑?
    • 1.单线程
    • 2.@Async和@EnableAsync
  • 二、使用多线程
  • 总结


前言

@Scheduled是spring自带的注解,默认是单线程,常用作定时任务使用,但是如果是集群版的机器的话,就考虑加上分布式锁或者使用分布式定时任务代替。

一、使用的那些坑?

1.单线程

因为@Scheduled默认使用的是单线程,如果有两个任务A和B,那么任务A要是阻塞了,任务B就无法执行。

2.@Async和@EnableAsync

为了解决单线程带来的线程阻塞问题,我们可以使用@Async和@EnableAsync两个注解采用异步的方式去处理,这样就是不同的线程去执行,但是这种方式也带来一个新的问题,那就是如果任务A的任务执行时间>任务调度周期时间的话,就会发生上一个任务未执行完毕,下一个任务又开始执行的逻辑,这种也是有风险的。所以最好使用多线程方式,自己控制线程池的数量,线程名称等。

二、使用多线程

需要实现SchedulingConfigurer接口,然后自定义线程池,这样凡是用到@Scheduled注解的都可以用该线程池,同时也解决了上述比较坑的两个问题。

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(20, (Runnable r) -> {
            Thread thread = new Thread(r);
            thread.setName("自定义线程名称");
            return thread;
        });
    }
}

以上这一行
thread.setName(“自定义线程名称”);
是设置线程名称,可以通过Thread.currentThread().getName()拿到该名称,便于在日志中进行排查问题。

总结

集群版本如果要使用@Scheduled的话,需要加分布式锁来控制,或者直接用分布式定时任务Elasticjob或者xxl-job等。

你可能感兴趣的:(Java实用型,java,spring,多线程)