spring boot 默认单线程排队跑定时任务问题记录

人盡茶涼 提交于 2019-12-14 22:40:15

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

** 问题描述:在使用springboot默认的定时任务时,若存在多个任务,框架默认只启动一个线程执行,会导致有些任务不能在指定时间开始执行**

** 另,关于分布式下定时任务同步锁问题,会再单独写一篇记录**

测试默认情况下定时任务的线程名称:

package com.example.demo.job;

import net.javacrumbs.shedlock.core.SchedulerLock;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableScheduling
public class TestJob {


    @Scheduled(cron = "0/5 * * * * ?")
    @SchedulerLock(name = "test1-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")
    public void execute1() {
        String curName = Thread.currentThread().getName();
        System.out.println("当前时间:" + LocalDateTime.now() + "  任务execute1对应的线程名: " + curName);
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Scheduled(cron = "0/5 * * * * ?")
    @SchedulerLock(name = "test2-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")
    public void execute2() {

        String curName = Thread.currentThread().getName();
        System.out.println("当前时间:" + LocalDateTime.now() + "  任务execute2对应的线程名: " + curName);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(cron = "0/10 * * * * ?")
    @SchedulerLock(name = "test3-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")
    public void execute3() {

        String curName = Thread.currentThread().getName();
        System.out.println("当前时间:" + LocalDateTime.now() + "  任务execute3对应的线程名: " + curName);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

结果如下:

spring boot 自带的定时任务默认只起一个线程:

这种情况下,对于有些定时任务若设定在某一固定时刻开始执行,就可能出现需要排队而不能准时执行的情况。然后找了下解决方案,我不太想巴拉源码了,网上大家都扒出来了,就是为空初始化一个线程那段,直接点上解决方案:

在启动类里面加上如下代码:

/**
	 *  解决定时任务单线程排队问题,建立线程池
	 * @return
	 */
	@Bean
	public TaskScheduler taskScheduler() {
		ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
		taskScheduler.initialize();
		taskScheduler.setPoolSize(50);
		return taskScheduler;
	}

然后重新启动看下线程的情况:

以及核心线程数:

这样就解决了单线程问题。

另:分布式情况下只能有一个定时任务在执行,防止重复执行的方案有很多,下次再写。

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!