likes
comments
collection
share

Spring Boot 定时器突然不执行原因

作者站长头像
站长
· 阅读数 12

前言

springboot的自动任务注解@EnableScheduling和@Scheduled底层原理是默认是单线程的,所以,线上有自动任务突然不执行,肯定是有自动任务线程发生阻塞或者死锁,导致卡住了,其他自动任务都无法执行,对外呈现一个程序假死的情况。

jstack查看线程

jstack pid >jstack.log 打印堆栈日志。

"scheduling-1" #47 prio=5 os_prio=0 tid=0x00007f8f42840000 nid=0x6708 runnable [0x00007f8eb34f3000]
   java.lang.Thread.State: RUNNABLE
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:197)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:378)
    - locked <0x0000000083919908> (a java.lang.Object)
    at oracle.net.nt.TimeoutSocketChannel.read(TimeoutSocketChannel.java:174)
    at oracle.net.ns.NSProtocolNIO.doSocketRead(NSProtocolNIO.java:560)
    at oracle.net.ns.NIOPacket.readPayload(NIOPacket.java:308)
    at oracle.net.ns.NIOPacket.readPacketFromSocketChannel(NIOPacket.java:212)
    at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:137)
    at oracle.net.ns.NIOPacket.readFromSocketChannel(NIOPacket.java:110)
    at oracle.net.ns.NIONSDataChannel.readDataFromSocketChannel(NIONSDataChannel.java:91)
    at oracle.jdbc.driver.T4CMAREngineNIO.prepareForUnmarshall(T4CMAREngineNIO.java:791)
    at oracle.jdbc.driver.T4CMAREngineNIO.unmarshalUB1(T4CMAREngineNIO.java:449)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:410)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:269)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:655)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:270)
    at oracle.jdbc.driver.T4CPreparedStatement.fetch(T4CPreparedStatement.java:1079)
    at oracle.jdbc.driver.OracleStatement.fetchMoreRows(OracleStatement.java:3456)
    at oracle.jdbc.driver.InsensitiveScrollableResultSet.fetchMoreRows(InsensitiveScrollableResultSet.java:742)
    at oracle.jdbc.driver.InsensitiveScrollableResultSet.absoluteInternal(InsensitiveScrollableResultSet.java:698)
    at oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:412)
    - locked <0x000000008390a510> (a oracle.jdbc.driver.T4CConnection)
    at com.p6spy.engine.wrapper.ResultSetWrapper.next(ResultSetWrapper.java:89)
    at com.zaxxer.hikari.pool.HikariProxyResultSet.next(HikariProxyResultSet.java)
    at org.hibernate.loader.Loader.processResultSet(Loader.java:986)
    at org.hibernate.loader.Loader.doQuery(Loader.java:948)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340)
    at org.hibernate.loader.Loader.doList(Loader.java:2689)
    at org.hibernate.loader.Loader.doList(Loader.java:2672)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2506)
    at org.hibernate.loader.Loader.list(Loader.java:2501)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1959)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)
    at org.teamartframework.core.common.dao.impl.GenericBaseCommonDao.getListByCriteriaQuery(GenericBaseCommonDao.java:754)
    at org.teamartframework.core.common.dao.impl.GenericBaseCommonDao$$FastClassBySpringCGLIB$$212185f1.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at org.teamartframework.core.common.dao.impl.CommonDao$$EnhancerBySpringCGLIB$$575df7cd.getListByCriteriaQuery(<generated>)
    at org.teamartframework.core.common.service.impl.CommonServiceImpl.getListByCriteriaQuery(CommonServiceImpl.java:290)
    at com.test.service.base.impl.DeviceServiceImpl.getListByCriteriaQuery(DeviceServiceImpl.java:190)
    at com.test.service.base.impl.DeviceServiceImpl.readData(DeviceServiceImpl.java:516)
    at com.test.service.base.impl.DeviceServiceImpl$$FastClassBySpringCGLIB$$1b52e2d4.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$573/569190647.proceedWithInvocation(Unknown Source)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.test.service.base.impl.DeviceServiceImpl$$EnhancerBySpringCGLIB$$beeaba43.readData(<generated>)
    at com.com.test.job.ReadJob.readData(ReadJob.java:32)
    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.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    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)

从上面日志可以看出

    at com.test.service.base.impl.DeviceServiceImpl.readData(DeviceServiceImpl.java:516)

执行的比较慢,针对这个查询进行优化,问题解决了。

Spring Boot 定时器突然不执行原因

线程池满

Spring Boot 使用线程池来执行定时任务,默认情况下使用的是 ThreadPoolTaskScheduler,默认线程数量是1,如果定时任务的执行时间超过了线程池的容量,会导致线程池满,后续的任务无法执行。

可以修改默认线程池数量:

spring:
    task:
      scheduling:
        pool:
          size: 2

任务抛出异常

如果定时任务在执行过程中抛出了异常并没有被捕获,那么该任务会停止执行,后续的任务也不会继续执行。

为了保证定时任务的连续执行,我们需要在任务执行过程中捕获异常并进行处理。可以在任务的执行方法中加入异常处理逻辑,将异常信息记录下来,以便后续分析和解决问题。

@Scheduled(cron = "0 0/5 * * * *")
    public void executeTask() {
        try {
            // 执行任务逻辑
        } catch (Exception e) {
            // 记录异常信息
        }
    }

定时任务的周期设置不合理

定时任务的周期设置不合理也可能导致任务停止执行。例如,如果我们将一个任务的执行周期设置为 5 秒,但任务的执行时间超过了 5 秒,那么任务就会停止执行。

总结

定时器突然停止执行可能是由线程池满、任务抛出异常和定时任务的周期设置不合理等原因引起的。为了解决这个问题,我们可以调整线程池的容量、捕获任务抛出的异常以及调整定时任务的周期。通过合理的设置和处理,我们可以保证定时任务的顺利执行。

转载自:https://juejin.cn/post/7343817438234066953
评论
请登录