spring boot 多线程并发执行定时任务

Spring Boot默认情况下,所有定时任务会在一个线程中去执行,下面看测试代码,定义了三个测试Job:

@Component
@Slf4j
public class TestJob {

    @Scheduled(cron = "0/3 * * * * ? ")
    public void job1() {

        log.info("do job1 start");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("do job1 end");

    }

    @Scheduled(cron = "0/7 * * * * ? ")
    public void job2() {

        log.info("do job2");
    }

    @Scheduled(cron = "0/13 * * * * ? ")
    public void job3() {

        log.info("do job3");
    }
}

理论上,如果互不干扰的话,三个任务的触发时间点为:

job1触发:0,3,6,9,12……

job2触发:0,7,14,21,28,35,42,49,56

job3触发:0,13,26,39,52

实际执行结果:

2019-03-01 14:59:24  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 14:59:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 14:59:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 14:59:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 14:59:35  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 14:59:36  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 14:59:46  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 14:59:46  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 14:59:46  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 14:59:48  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 14:59:58  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 14:59:58  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 14:59:58  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:00:00  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:00:00  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:00:00  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:00:10  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:00:10  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:00:12  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:00:22  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:00:22  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:00:22  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:00:24  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:00:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:00:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:00:34  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:00:35  INFO 7868 --- [   scheduling-1] c.yclouds.service.demo.TestJob  : do job2

会看到他们的线程名都为schedule-1,观察line1-4,job1执行过程中,job2,job3触发时间到了,也没有执行。而是等job1结束后,立马执行一次(即使34秒的时候并不是它们的触发时间)。

上干货,并发执行多个定时任务,只需要新增一个线程池配置即可:

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

        // 设置线程池
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setThreadNamePrefix("Schedule-Task-");
        taskScheduler.setPoolSize(5);
        taskScheduler.initialize();

        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
    }
}

下面再来看执行结果:

2019-03-01 15:21:00  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:21:00  INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:00  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:21:07  INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:10  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:21:12  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:21:13  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:21:14  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:21  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:22  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:21:24  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:21:26  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:21:28  INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:34  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:21:35  INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:36  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:21:39  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:21:42  INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:46  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:21:48  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:21:49  INFO 11204 --- [Schedule-Pool-4] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:52  INFO 11204 --- [Schedule-Pool-2] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:21:56  INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:21:58  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 end
2019-03-01 15:22:00  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 start
2019-03-01 15:22:00  INFO 11204 --- [Schedule-Pool-1] c.yclouds.service.demo.TestJob  : do job3
2019-03-01 15:22:00  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:22:07  INFO 11204 --- [Schedule-Pool-3] c.yclouds.service.demo.TestJob  : do job2
2019-03-01 15:22:10  INFO 11204 --- [Schedule-Pool-0] c.yclouds.service.demo.TestJob  : do job1 end

三个任务都在各自的线程里执行,到点就触发,互不干扰。

 

GitHub地址:https://github.com/ye17186/spring-boot-learn

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: Spring Boot支持多线程编程,主要有以下几种方式: 1. 继承Thread类或实现Runnable接口 这是最基本的多线程编程方式,可以在Spring Boot中使用。开发者可以通过继承Thread类或实现Runnable接口,重写run()方法实现多线程逻辑。示例代码: ```java public class MyThread extends Thread { @Override public void run() { // 多线程逻辑 } } public class MyRunnable implements Runnable { @Override public void run() { // 多线程逻辑 } } // 使用 new MyThread().start(); new Thread(new MyRunnable()).start(); ``` 2. 使用线程池 线程池可以有效地管理多个线程,避免创建和销毁线程的开销。Spring Boot提供了ThreadPoolTaskExecutor类,可以用来创建和管理线程池。示例代码: ```java @Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(30); executor.initialize(); return executor; } } // 使用 @Async public void doSomething() { // 多线程逻辑 } ``` 3. 使用CompletableFuture CompletableFuture是Java 8引入的异步编程方式,可以很方便地实现多线程编程。Spring Boot也提供了对CompletableFuture的支持。示例代码: ```java public CompletableFuture<String> doSomething() { CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 多线程逻辑 return "result"; }); return future; } ``` 以上是Spring Boot多线程编程的三种方式,开发者可以根据具体的业务场景选择不同的方式。 ### 回答2: Spring Boot是一个用于快速构建基于Spring框架的应用程序的工具。在Spring Boot中,可以轻松地实现多线程的功能。 Spring Boot提供了多种方式来实现多线程。一种常用的方式是使用`@Async`注解来标记一个方法为异步方法。在使用`@Async`注解之后,该方法将会在一个单独的线程中执行,而不会阻塞主线程。通过使用这个注解,可以在应用程序中执行耗时操作,而不会影响其他的业务逻辑。需要注意的是,要实现异步方法,还需要在应用程序的主类上添加`@EnableAsync`注解。 除了使用`@Async`注解外,Spring Boot还提供了`ThreadPoolTaskExecutor`类来方便地创建线程池。通过配置线程池的大小、最大线程数等参数,可以实现更加灵活和高效的多线程处理。可以在应用程序的配置文件中添加以下配置来创建线程池: ```java @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); executor.setThreadNamePrefix("taskExecutor-"); executor.initialize(); return executor; } } ``` 上述配置创建了一个线程池,核心线程数为5,最大线程数为10,队列容量为25。通过将`@Async`注解和`taskExecutor`作为参数添加到方法中,即可实现多线程的功能。 综上所述,Spring Boot提供了多种方式来实现多线程。使用`@Async`注解可以快速实现异步方法,而`ThreadPoolTaskExecutor`类则提供了更加灵活和高效的线程池配置。这些功能可以帮助我们提高应用程序的性能和并发处理能力。 ### 回答3: Spring Boot多线程允许开发者在应用程序中使用并发处理来提高性能和效率。它基于Java的多线程机制,但通过Spring Boot可以更加方便地进行配置和管理。 Spring Boot使用了Java的Executor框架来处理线程池和线程管理。开发者可以通过@EnableAsync注解启用异步方法和@Async注解将方法标记为异步执行。这样在调用该方法时,Spring Boot会自动创建一个新的线程执行该方法,而当前线程则不会被阻塞。 使用多线程可以提高应用程序的响应性能,特别是在处理一些耗时的操作时。通过异步方法,可以将一些需要等待的操作转移到后台线程中执行,不影响主线程继续执行其他操作。这对于处理大量请求或者IO密集型的任务非常有用。 在配置多线程时,开发者可以指定线程池的大小、最大线程数、线程的生命周期等参数。这些参数可以根据具体的应用场景进行调整,以达到最佳的性能和资源利用。同时,Spring Boot还提供了一些方便的工具类和注解,用于处理线程间的数据共享和同步,如通过ThreadLocal存储线程局部变量,通过@Lock注解实现对指定资源的加锁。 总之,Spring Boot多线程提供了一种便捷的方式来管理并发处理,使得开发者能够更加轻松地实现并行执行和异步操作。它可以大大提高应用程序的性能和响应能力,适用于处理一些耗时的任务和IO密集型的操作。但同时也需要注意线程安全和资源管理的问题,合理配置和使用多线程,才能充分发挥其潜力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值