当前位置: 首页 > 知识库问答 >
问题:

是什么原因导致Spring调度器在应用程序和servlet启动之前执行?

钱劲
2023-03-14

我有一个简单的Spring-Boot web应用程序,其中有一些调度任务:

@SpringBootApplication
@EnableScheduling
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(final SpringApplicationBuilder app) {
        return app.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

和执行两个调度任务的服务:

@Service
public class SchedulingService {

    @Scheduled(fixedRate = 15000)
    private void first() {
        // log first
    }

    @Scheduled(fixedRate = 6000)
    public void second() {
        // log second
    }
}

有没有解释说明为什么在应用程序和servlet启动之前执行了其中一个调度任务?这种情况反复发生,日志顺序总是相同的,所以我怀疑多线程没有发生--第一个调度任务和第二个调度任务之间有将近一秒的差异。

2018-08-18 20:47:53.085信息251168--[ost-startStop-1]O.S.B.A.W.S.WelcomePageHandlerMapping:添加欢迎页面模板:索引

2018-08-18 20:47:53.300信息251168--[ost-startStop-1]O.S.J.E.A.AnnotationMBeanExporter:在启动时为JMX公开注册bean

2018-08-18 20:47:53.314信息251168--[ost-startStop-1]S.A.ScheduleDanNotationBeanPostProcessor:找不到用于计划处理的TaskScheduler/ScheduleDexecutorService bean

2018-08-18 20:47:53.321此处首次登录

2018-08-18 20:47:53.344信息251168--[ost-startStop-1]my.appname.Application:5.565秒启动应用程序(JVM运行16.93)

2018-08-18 20:47:53.396信息251168---[main]org.apache.coyote.ajp.ajpnioprotocol:启动协议处理程序[“ajp-nio-8009”]

2018-08-18 20:47:53.400信息251168---[main]org.apache.catalina.startup.catalina:服务器启动15970 ms

2018-08-18 20:47:53.477信息251168---[nio-8080-exec-1]O.A.C.C.C.[.[localhost].[/rattle]:正在初始化Spring FrameworkServlet“Dispatcher Servlet”

2018-08-18 20:47:53.477信息251168--[nio-8080-exec-1]o.s.web.servlet.DispatcherServlet:FrameworkServlet“Dispatcher Servlet”:初始化已启动

2018-08-18 20:47:53.520信息251168--[nio-8080-exec-1]o.s.web.servlet.DispatcherServlet:FrameworkServlet“Dispatcher Servlet”:初始化在43毫秒内完成

2018-08-18 20:47:54.103此处登录秒

2018-08-18 20:47:59.335此处登录秒

2018-08-18 20:48:08.334此处首次登录

共有1个答案

慕光霁
2023-03-14

我只是创建了一个空的SpringBoot项目,添加了您的类,并尝试重现相同的问题。在SpringBoot2.0.4.release上,我看到两个任务在同一时间和同一线程运行:

2018-08-18 21:16:54.145  INFO 10239 --- [pool-1-thread-1] com.test.SchedulingService               : LOG FIRST
2018-08-18 21:16:54.145  INFO 10239 --- [pool-1-thread-1] com.test.SchedulingService               : LOG SECOND

然后,我在这两个任务上添加了thread.sleep(100),因为我无法预测执行顺序。

2018-08-18 21:21:14.775  INFO 10274 --- [pool-1-thread-1] com.test.SchedulingService               : LOG FIRST
2018-08-18 21:21:14.878  INFO 10274 --- [pool-1-thread-1] com.test.SchedulingService               : LOG SECOND

日志条目之间的aprox延迟100ms,确认它们运行在同一线程上。

我找到的解决方案是定义一个自定义bean,该自定义bean创建CustomTaskScheduler:

@Bean()
public  ThreadPoolTaskScheduler  taskScheduler(){
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(2);
    taskScheduler.setThreadNamePrefix("Async-");
    return  taskScheduler;
}

现在,日志显示两个任务同时执行,并且由不同的线程执行:

2018-08-18 21:30:26.482  INFO 10383 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-08-18 21:30:26.486  INFO 10383 --- [           main] com.test.ProjectApplication              : Started ProjectApplication in 1.767 seconds (JVM running for 2.137)
2018-08-18 21:30:26.555  INFO 10383 --- [        Async-2] com.test.SchedulingService               : LOG SECOND
2018-08-18 21:30:26.555  INFO 10383 --- [        Async-1] com.test.SchedulingService               : LOG FIRST

我定义了size=2线程池。如果我有3个任务要运行,会发生什么?其中一个任务将需要等待完成前面2的执行,获得线程释放并再次检查执行队列。

2018-08-18 21:33:48.895  INFO 10412 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-08-18 21:33:48.899  INFO 10412 --- [           main] com.test.ProjectApplication              : Started ProjectApplication in 1.888 seconds (JVM running for 2.258)
2018-08-18 21:33:48.960  INFO 10412 --- [        Async-1] com.test.SchedulingService               : LOG FIRST
2018-08-18 21:33:48.960  INFO 10412 --- [        Async-2] com.test.SchedulingService               : LOG SECOND
2018-08-18 21:33:49.065  INFO 10412 --- [        Async-2] com.test.SchedulingService               : LOG THIRD
 类似资料:
  • 问题内容: 我使用JSP构建Web应用程序,并且在我的servlet中,我具有: 到现在为止,当JSP页面调用like时,我的serlvet都被调用了。我想要的是每当应用程序启动时也要执行的servlet。我可以在第一页上有一个类似“ START”的按钮,并在那里调用servlet。但是,我可以避免这种情况吗? 问题答案: 无论您想在启动时做什么,都应该由实现的类完成,因此您应该编写这样的类,例如

  • 问题内容: 和之间有什么区别? 是什么导致它们被抛出?如何解决? 在修改现有代码以包含新的jar文件时,我经常遇到这些throwables。我在客户端和服务器端都通过Webstart分发了一个Java应用程序。 我遇到的可能原因: build.xml代码客户端未包含的软件包 我们正在使用的新jar缺少运行时类路径 版本与先前的jar冲突 今天,当我遇到这些问题时,我会采取一种犯错的方法来使事情正常

  • 理想情况下,我们可以对客户机和/或服务器进行一些配置,以减少这些异常的发生率,但我不太了解SPDY,甚至不知道从哪里开始查找,也不建议我们的服务器管理团队开始查找。 堆栈跟踪,以防有帮助:

  • 问题内容: 和之间有什么区别? 是什么导致它们被抛出?如何解决? 在修改现有代码以包含新的jar文件时,我经常遇到这些throwables。我在客户端和服务器端都通过Webstart分发了一个Java应用程序。 我遇到的可能原因: 代码客户端未包含的软件包 我们正在使用的新jar缺少运行时类路径 版本与先前的jar冲突 今天,当我遇到这些问题时,我会采取一种犯错的方法来使事情正常进行。我需要更多的

  • 我有一个使用Spring Boot Actuator的Java后端,但它不会在DigitalOcean Ubuntu VPS上启动。同样的应用程序在我的苹果电脑和其他Ubuntu电脑上运行良好。 它开始初始化,但每次都在同一点停止(没有例外,只是挂起)。如果我尝试在此时用停止它,它将无法恢复shell。 这是Outoput: 这是之后的输出: 有人面临过同样的问题吗?你们能帮帮我吗? 这里你有线程

  • 正如标题所示,我正在寻找任何可以帮助我在Springs应用程序上下文(准确地说是持久性上下文)加载之前运行Flyway迁移的方法。原因是我在应用程序启动时运行的查询很少。这导致我的测试失败,因为正在对尚不存在的数据库表执行查询。我使用H2作为我的测试数据库。现在我只使用flyway核心依赖: 我有一个单一的Flyway配置类,如下所示: 并且属性在 我想实现的是:1.飞行路线做迁移2。Spring