Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当作业重叠时,spring@scheduled cron的预期行为是什么?_Java_Spring_Cron - Fatal编程技术网

Java 当作业重叠时,spring@scheduled cron的预期行为是什么?

Java 当作业重叠时,spring@scheduled cron的预期行为是什么?,java,spring,cron,Java,Spring,Cron,我有一个每小时运行一次的作业,我正在使用Spring的@scheduled cron来安排它 如果作业需要一个多小时,我从中了解到,在第一个作业运行时,下一个作业不会启动 但这是否意味着它将在第一项工作完成后启动,还是错过了机会 如果我有一个作业需要10小时,那么所有错过的cron作业会排队,然后在10小时后第一个作业完成时逐个执行,还是只运行第一个作业 谢谢 默认情况下,执行是阻塞和单线程的,这意味着它们不会同时运行。如果希望作业同时运行,还可以将该方法注释为@Async。你可能还想看看不同的

我有一个每小时运行一次的作业,我正在使用Spring的@scheduled cron来安排它

如果作业需要一个多小时,我从中了解到,在第一个作业运行时,下一个作业不会启动

但这是否意味着它将在第一项工作完成后启动,还是错过了机会

如果我有一个作业需要10小时,那么所有错过的cron作业会排队,然后在10小时后第一个作业完成时逐个执行,还是只运行第一个作业


谢谢

默认情况下,执行是阻塞和单线程的,这意味着它们不会同时运行。如果希望作业同时运行,还可以将该方法注释为
@Async
。你可能还想看看不同的

如果您使用的是与您提供的示例问题类似的
fixedDelay
,则只有在当前作业结束并加上延迟后,下一个作业才会开始。因此,如果您的工作需要10小时,并且您的
固定延迟
5000
,则下一个工作将在10小时后5秒开始

如果您使用的是
fixedRate
,则下一个计划事件将排队运行,但不会跳过,如下所示:

如果此任务的任何执行时间超过其周期,则 后续执行可能会延迟开始,但不会同时执行 执行

如果只是使用
cron
,那么作业将依次排队和执行(类似于
fixedRate
)。您可以使用一个简单的方法来测试这一点(下面是Groovy,但也可以使用普通Java):

inti=0
@已计划(cron='***')
无效测试(){
如果(i<5)
线程。睡眠(10000)
i+=1
println'---------------------------'+i//未跳过任何值
}

你会注意到每个数字都是打印出来的;e、 g.任何周期都不会被跳过。

fixedRate
cron
的行为是不同的


重叠作业排队等待
fixedRate
(根据@Igor的上述回答)

对于
cron
,将跳过重叠作业

演示差异的示例Java代码:

int i = 0;
@Scheduled(fixedRate = 5000)
public void test() throws InterruptedException {
    Date start = new Date();
    if (i < 3) Thread.sleep(10000);
    i++;
    System.out.printf("start %TT, finish %TT, i = %s%n", start, new Date(), i);
}
如图所示,重叠作业将排队,并在前一个作业完成后立即开始,没有5秒的间隔

但是,如果我们使用
@Scheduled(cron=“*/5**?**”)来代替
,则输出将变为:

start 13:22:10, finish 13:22:20, i = 1
start 13:22:25, finish 13:22:35, i = 2
start 13:22:40, finish 13:22:50, i = 3
start 13:22:55, finish 13:22:55, i = 4
start 13:23:00, finish 13:23:00, i = 5
start 13:23:05, finish 13:23:05, i = 6
start 13:23:10, finish 13:23:10, i = 7
start 13:23:15, finish 13:23:15, i = 8
start 13:23:20, finish 13:23:20, i = 9
start 13:23:25, finish 13:23:25, i = 10

两个工作之间总是有5秒的间隔。重叠作业不排队,将被跳过。

重叠作业将排队等待fixedRate,并将跳过@firstmanonmars提到的cron

如果我们希望在不等待的情况下执行相互重叠的corn调度程序,我们可以使用@Async@EnableAsync,如下所示

@EnableScheduling
@SpringBootApplication
@EnableAsync

public class TaskSchedulerApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskSchedulerApplication.class, args);
    }
    
    @Bean
    public TaskScheduler taskScheduler() {
        final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        return scheduler;
    }
}
调度程序演示:

@Component
public class DemoScheduler {
    
    @Async
    @Scheduled(cron = "*/5 * * * * MON-FRI")
    public void startJob() {
        System.out.println(String.format("%s - Thread name - %s ",new Date(), Thread.currentThread().getName()));
        sleep(6000);
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Thu May 06 09:59:05 IST 2021 - Thread name - task-1 
Thu May 06 09:59:10 IST 2021 - Thread name - task-2 
Thu May 06 09:59:15 IST 2021 - Thread name - task-3 
Thu May 06 09:59:20 IST 2021 - Thread name - task-4 
Thu May 06 09:59:25 IST 2021 - Thread name - task-5 
Thu May 06 09:59:30 IST 2021 - Thread name - task-6 
Thu May 06 09:59:35 IST 2021 - Thread name - task-7 
Thu May 06 09:59:40 IST 2021 - Thread name - task-8 
Thu May 06 09:59:45 IST 2021 - Thread name - task-1 
Thu May 06 09:59:50 IST 2021 - Thread name - task-2 
Thu May 06 09:59:55 IST 2021 - Thread name - task-3
运行代码会得到以下输出,显示它们由多个线程以5秒的间隔并行运行:

@Component
public class DemoScheduler {
    
    @Async
    @Scheduled(cron = "*/5 * * * * MON-FRI")
    public void startJob() {
        System.out.println(String.format("%s - Thread name - %s ",new Date(), Thread.currentThread().getName()));
        sleep(6000);
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Thu May 06 09:59:05 IST 2021 - Thread name - task-1 
Thu May 06 09:59:10 IST 2021 - Thread name - task-2 
Thu May 06 09:59:15 IST 2021 - Thread name - task-3 
Thu May 06 09:59:20 IST 2021 - Thread name - task-4 
Thu May 06 09:59:25 IST 2021 - Thread name - task-5 
Thu May 06 09:59:30 IST 2021 - Thread name - task-6 
Thu May 06 09:59:35 IST 2021 - Thread name - task-7 
Thu May 06 09:59:40 IST 2021 - Thread name - task-8 
Thu May 06 09:59:45 IST 2021 - Thread name - task-1 
Thu May 06 09:59:50 IST 2021 - Thread name - task-2 
Thu May 06 09:59:55 IST 2021 - Thread name - task-3

cronjoby在单独的线程中执行。因此,当它的时间到了,一个新的线程就会产生并执行,而不管以前的执行是否是竞争的。(如果您使用fixeddelay,则它将等待以前运行的任务完成)@pvpkiran您的评论不正确。如果上一次迭代正在运行,spring计划的cron作业将不会启动,无论您有什么执行者-请参阅我链接的答案中的第二个答案。我相信Igor答案中的示例与您的断言相矛盾,即“cronjob在单独的线程中执行。因此,当它的时间到了,一个新的线程就会产生并执行,而不管以前的执行是否是竞争的。“返回的数字顺序与您的型号不符。谢谢-但您还没有回答我的问题。@Bruce更新。没有代码,这有点模棱两可,因为我以为你在问fixedDelay/fixedRate的交互w/cron.Ah好的,谢谢-你的编辑确实回答了这个问题。谢谢这不是答案,因此更适合作为评论。请查看SO指南。谢谢,我已经改进了答案,包括一个示例。