­

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

  • 2019 年 12 月 15 日
  • 筆記

作者:小小明童鞋

链接:https://my.oschina.net/xiaomingnevermind/blog/3143095

问题描述:在使用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;  	}

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

以及核心线程数:

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

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