定时任务@Scheduled之单线程多线程问题

现象

在一个类内,写了两个定时任务,发现它们竟然是串行执行的。
于是想到, @Scheduled 该不会是单线程执行折吧?

于是找了一下,发现还真的是。。。

可参考: https://blog.csdn.net/Mr_EvanChen/article/details/103408290

另外:
(1)一个定时任务,会占用一个线程,直至结束,才会开始下一次的任务,并不会出现,“到点就执行”的情况。
比如有两个定时任务,都是每1分钟执行一次,但其中一个执行一次耗时10个小时,

那么执行的情况如下:
00:00:任务1第一次触发,占用线程1。
01:00:任务1第二次触发,等待线程1释放。
02:00:任务1第三次触发,等待线程1释放。
...
10:00:任务1第一次执行完成,线程1释放。
10:00:任务1第二次触发,占用线程1开始执行。
11:00:任务1第三次触发,等待线程1释放。

解决方案

1、添加配置:spring.task.scheduling.pool.size=20
这个方法更为简便。至于要开多少个线程来用于执行定时任务,需要根据业务实际情况来确定了。

2、ScheduledTaskRegistrar 有一个 setScheduler() 方法,
可以通过这个方法,设置它的执行线程池。。。改为多核心线程数的线程池。

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(50));
    }

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(10);
        threadPoolTaskScheduler.setThreadNamePrefix("My-Schedule: ");
        threadPoolTaskScheduler.initialize();
        return threadPoolTaskScheduler;
    }
}

2、在原来的模块,加 上这个配置,它就变成多线程执行了。

注意

这种方法,每次定时任务启动的时候,都会创建一个单独的线程来处理。也就是说同一个定时任务也会启动多个线程处理。
例如:任务1和任务2一起处理,但是线程1卡死了,任务2是可以正常执行的。且下个周期,任务1还是会正常执行,不会因为上一次卡死了,影响任务1。
但是任务1中的卡死线程越来越多,会导致50个线程池占满,还是会影响到定时任务。

所以,如果发现有定时任务会长时间卡住,还是赶紧解决掉才行呀~

posted @ 2023-11-02 17:28  aaacarrot  阅读(510)  评论(0)    收藏  举报