加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在自己的线程中运行每个Spring Scheduler

发布时间:2020-12-14 06:02:18 所属栏目:Java 来源:网络整理
导读:我有多个带有@Scheduled注释的组件,我发现 Spring一次只启动一个,即使它们被安排在同一时间运行. 我的用例如下.我希望每个@Scheduled注释都在自己的线程中运行,但每个线程只运行一次. 给定这个带有两个调度程序的伪代码: @Scheduled(cron = "0 * * * * *")
我有多个带有@Scheduled注释的组件,我发现 Spring一次只启动一个,即使它们被安排在同一时间运行.

我的用例如下.我希望每个@Scheduled注释都在自己的线程中运行,但每个线程只运行一次.

给定这个带有两个调度程序的伪代码:

@Scheduled(cron = "0 * * * * *") //run every minute
public void methodA() {
   log.info("Running method A");
   executeLongRunningJob("Finished method A");
}

@Scheduled(cron = "0 * * * * *") //run every minute
public void methodB() {
   log.info("Running method B");
   executeLongRunningJob("Finished method B");       
}

private void executeLongRunningJob(String msg) {
    Thread.sleep(70 seconds);
    System.out.println(msg);
}

请注意,该任务所需的时间比计划的调度程序运行时间长.这很关键.我不希望调度程序在完成运行之前重新启动.

从开箱即用运行此代码为我提供了以下输出:

Running method A
Finished method A
Running method B
Finished method B
Running method A
Finished method A
Running method B
Finished method B
... and so on

显然它在一个线程中运行两个调度程序.

当我把@Async放在我昂贵的方法上时,我几乎得到了正确的行为,除了在新的调度程序启动之前没有完成昂贵的方法.

Running method A
Running method B
Running method A
Running method B
Finished method A
Finished method B
... and so on

我想要的是这个输出:

Running method A  
Running method B
Finished method A 
Finished method B 
Running method A 
Running method B 
Finished method A 
Finished method B
... and so on

我怎么能做到这一点?
我希望每个调度程序同时运行,但等到它完成后再允许再次运行.
请记住,我有两个以上的调度程序在相同且有时不同的时间运行.

解决方法

你没错 – 默认情况下,调度程序使用大小为1的线程池,因此每个任务都按顺序处理.您可以通过配置具有所需池大小的 TaskScheduler bean来实现.考虑以下示例:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.Date;

@SpringBootApplication
@EnableScheduling
public class Application {

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

    @Bean
    public TaskScheduler taskScheduler() {
        final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        return scheduler;
    }


    @Scheduled(fixedDelay = 2 * 1000L,initialDelay = 3 * 1000L)
    public void scheduled1() throws InterruptedException {
        System.out.println(new Date() + " " + Thread.currentThread().getName() + ": scheduled1");
        Thread.sleep(1000);
    }

    @Scheduled(fixedDelay = 3 * 1000L,initialDelay = 3 * 1000L)
    public void scheduled2() throws InterruptedException {
        System.out.println(new Date() + " " + Thread.currentThread().getName() + ": scheduled2");
        Thread.sleep(1000);
    }
}

它将在单独的线程中运行每个计划任务,例如:

Tue Jul 18 20:21:50 CEST 2017 taskScheduler-1: scheduled2
Tue Jul 18 20:21:50 CEST 2017 taskScheduler-2: scheduled1
Tue Jul 18 20:21:53 CEST 2017 taskScheduler-1: scheduled1
Tue Jul 18 20:21:54 CEST 2017 taskScheduler-3: scheduled2
Tue Jul 18 20:21:56 CEST 2017 taskScheduler-2: scheduled1
Tue Jul 18 20:21:58 CEST 2017 taskScheduler-4: scheduled2
Tue Jul 18 20:21:59 CEST 2017 taskScheduler-1: scheduled1

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读