欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

定时任务的并发_03

程序员文章站 2024-03-22 17:02:52
...

正常定时任务场景
定时任务的并发_03
任务1从第0秒开始执行,执行3秒结束
任务1再从第5秒开始执行,执行3秒结束,以此类推

每一个任务执行都不会有冲突,都不会有干扰,在规定的5秒时间内,任务1都能执行完成

定时任务的并发场景
定时任务的并发_03
什么是定时任务的并发?
任务2从第0秒开始执行,执行7秒结束,这个定时任务
任务2再从第5秒开始执行,这时第一个定时任务由于数量大尚未执行完成,任务2 开始第2次任务开始,执行7秒结束,但是,任务2执行的第一次和执行第二次有重叠部分,这一部分成为定时任务的并发,这一部分有可能处理相同的数据。
案例理解:在定时定点给一个用户发短信,一个用户只发一次,如果是定时任务并发,有可能给同一个用户发送2次短信

定时任务并发代码演示:

package com.gblfy.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalTime;

public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        LocalTime localTime = LocalTime.now();
        System.out.println(Thread.currentThread().getName()+"开始执行!" + localTime);

        try {
            //休眠7秒
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime endTime = LocalTime.now();
        System.out.println(Thread.currentThread().getName()+"结束执行!" + endTime);
    }
}

定时任务的并发_03

找一组分析一下:
Worker-1开始执行!17:55:08
Worker-2开始执行!17:55:12
Worker-1结束执行!17:55:15
Worker-3开始执行!17:55:17
Worker-2结束执行!17:55:19
Worker-1开始执行!17:55:22
Worker-3结束执行!17:55:24

定时任务并发数据开始分析:
Worker-1和Worker-2 开始执行间隔5秒
Worker-1 开始执行和Worker-1 结束执行 间隔7秒

Worker-2和Worker-3 开始执行间隔5秒
Worker-2 开始执行和Worker-2 结束执行 间隔7秒

Worker-3和Worker-1 开始执行间隔5秒
Worker-3 开始执行和Worker-3 结束执行 间隔7

如何防止定时任务并发?
在Job类上添加@DisallowConcurrentExecution注解

防止并发示例

package com.gblfy.job;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalTime;

@DisallowConcurrentExecution
public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        LocalTime localTime = LocalTime.now();
        System.out.println(Thread.currentThread().getName() + "开始执行!" + localTime);

        try {
            //休眠7秒
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime endTime = LocalTime.now();
        System.out.println(Thread.currentThread().getName() + "结束执行!" + endTime);
    }
}

定时任务的并发_03

找一组分析一下:
Worker-1开始执行!18:08:17
Worker-1结束执行!18:08:24
Worker-2开始执行!18:08:24
Worker-2结束执行!18:08:31
Worker-3开始执行!18:08:31
Worker-3结束执行!18:08:38
Worker-1开始执行!18:08:42
Worker-1结束执行!18:08:49

定时任务并发数据开始分析:
Worker-1 开始执行和结束执行 间隔7秒
Worker-2 开始执行和结束执行 间隔7秒
Worker-3 开始执行和结束执行 间隔7秒

Worker-2 第一次执行应该是 Worker-2开始执行!18:08:22,但是由于Worker-1还没有结束,等待Worker-1执行完成后,Worker-2开始执行

Worker-3 第一次执行应该是 Worker-3开始执行!18:08:27,但是由于Worker-2 还没有结束,等待Worker-2执行完成后,Worker-3开始执行

Worker-1 第二次执行应该是 Worker-1 开始执行!18:08:32,但是由于Worker-3 还没有结束,等待Worker-3 执行完成后,Worker-1开始执行,单这次定时任务会触发Qartz的Misfire的错过机制,等到下一个节点执行第2次的Worker-1 

Worker-3结束执行!18:08:38
Worker-1开始执行!18:08:42
从以上数据,可以看出,当地二次执行 Worker-1时,按照上面的规则应该是Worker-1开始执行!18:08:38,对吧?
第1次错过:执行Worker-22次错过:执行Worker-3
当错过2次定时任务,就会Qartz的Misfire的错过机制

Qartz的Misfire的错过机制:
当定时任务错过2次,之后会触发Qartz的Misfire的错过机制,触发及之后,上面的错过的2次定时任务会取消,等到下一个节点执行定时任务。