spring boot 定时任务在启动时执行几次 就不执行了

定时任务执行几次就不执行了

  • 背景
  • 分析方案
  • 解决方案
  • 附录1

背景

今天debug项目时发现所有定时任务在程序启动时执行几次后就不执行了
检查代码也没发现有什么问题 通过jstack查看线程信息时 发现只有一个名字为scheduling-1的线程 而且还是time-waiting状态的 分析调用链发现是手动调用了Thread.sleap方法导致
原因: 项目中有多个定时任务要运行 而只有一个核心线程 还是阻塞的 所以其他定时任务得不到执行

分析方案

jstack 25097|grep scheduling -A 10

查看结果请点击附录1

解决方案

为定时任务配置线程池 让它支持多线程
asyncTaskExecutor 针对@Async方法
taskScheduler 针对@Scheduled方法

public class TaskConfig {
    public TaskConfig() {
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnAnnotation(EnableAsync.class)
    public AsyncTaskExecutor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(12);
        executor.setQueueCapacity(20);
        executor.setMaxPoolSize(50);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("async-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        executor.setRejectedExecutionHandler(RejectedExecutionHandlers.discardPolicy());
        return executor;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnAnnotation(EnableScheduling.class)
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(8);
        scheduler.setThreadNamePrefix("task-");
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        scheduler.setAwaitTerminationSeconds(60);
        return scheduler;
    }
}
@Import({TaskConfig.class})
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableTaskMultiThreading {
}

@EnableTaskMultiThreading 开启任务多线程支持

@SpringBootApplication
@EnableScheduling
@EnableTaskMultiThreading
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(XynetServiceStatisticsApplication.class, args);
	}
}

附录1

nailsoul@nailsoul-company-pc:~$ jstack 25097|grep scheduling -A 10
"scheduling-1" #81 prio=5 os_prio=0 tid=0x00007fd556891000 nid=0x629a waiting on condition [0x00007fd52d69f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.xynet.cloud.core.util.ThreadUtil.sleep(ThreadUtil.java:6)
	at com.xynet.statistics.service.impl.StatisticsLeakyScreenScanningServiceImpl.scannerStatisticsLeakyScreenDatasByType(StatisticsLeakyScreenScanningServiceImpl.java:184)
	at com.xynet.statistics.service.impl.StatisticsLeakyScreenScanningServiceImpl.scannerStatisticsLeakyScreenTaskByCrontab(StatisticsLeakyScreenScanningServiceImpl.java:123)
	at com.xynet.statistics.service.impl.StatisticsLeakyScreenScanningServiceImpl.scannerStatisticsLeakyScreenDatas(StatisticsLeakyScreenScanningServiceImpl.java:79)
	at com.xynet.statistics.config.StatisticsSchedule.startRecordLeakyScreenScanner(StatisticsSchedule.java:123)
	at com.xynet.statistics.config.StatisticsSchedule$$FastClassBySpringCGLIB$$e54fcc5a.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
--
	at org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAspect.traceBackgroundThread(TraceSchedulingAspect.java:73)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
--
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
	at org.springframework.cloud.sleuth.instrument.async.TraceRunnable.run(TraceRunnable.java:67)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
	
nailsoul@nailsoul-company-pc:~$ 

你可能感兴趣的:(spring boot 定时任务在启动时执行几次 就不执行了)