前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一图理解quartz任务调度及注意事项

一图理解quartz任务调度及注意事项

作者头像
崔认知
发布2023-11-20 10:07:25
5860
发布2023-11-20 10:07:25
举报
文章被收录于专栏:nobodynobody

1、单机任务调度,任务可能会重叠并发执行。

如示例:每隔10秒执行此任务,但是任务执行耗时20s

执行结果(任务重叠执行):

解决:单机可加注解DisallowConcurrentExecution解决,集群环境必须靠分布式如quartz集群方案解决,如果保证不了任务的重叠执行,可以用分布式锁或任务执行幂等性来保证。

示例:使用注解DisallowConcurrentExecution解决效果:

执行结果:

2、使用注解DisallowConcurrentExecution来解决任务重叠问题,可能由于任务执行时间长,导致任务调度不准确

示例:

执行结果(任务调度周期与耗时相关,不再准确---每隔10s执行,耗时20s):

如果运行任务重叠执行,则(任务调度周期为准-每隔10s执行):

产生1、2现象的原因在于获取可被调度的任务时(默认内存存储任务job及调度信息):

代码语言:javascript
复制
org.quartz.simpl.RAMJobStore#acquireNextTriggers

当获取任务的触发器时,同时也会删除其存储信息

任务被真正调度之前,根据是否可以重叠执行,如果可以重叠执行,则重新把触发器添加存储起来,下次任务调度轮询可以被再次调度

代码语言:javascript
复制
org.quartz.simpl.RAMJobStore#triggersFired

任务被执行完时不能重叠执行的任务也会被重新存储起来,下次任务调度轮询可以被再次调度:

代码语言:javascript
复制
org.quartz.simpl.RAMJobStore#triggeredJobComplete

3、任务会因为任务线程池没有空闲线程执行,导致调度线程等待,任务不会再被调度

任务调度线程获取的任务会交给工作线程池去调度,默认是固定大小的线程池SimpleThreadPool,如果线程池没有空闲线程执行任务,则调度线程会一直等待:

代码语言:javascript
复制
org.quartz.core.QuartzSchedulerThread#run
代码语言:javascript
复制
org.quartz.simpl.SimpleThreadPool#blockForAvailableThreads

实现:

4、如果任务需要停止继续被调度,可以抛出异常JobExecutionException,设置信息:

根据异常信息转换为CompletedExecutionInstruction:

根据CompletedExecutionInstruction判断任务是否能被继续调度:

代码语言:javascript
复制
org.quartz.simpl.RAMJobStore#triggeredJobComplete

附:

代码语言:javascript
复制
package com.renzhikeji.demo;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.concurrent.TimeUnit;

public class QuartzDemo {
    public static void main(String[] args) throws SchedulerException, InterruptedException {
        //创建调度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //创建触发器
        Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
                                        .build();

        //定义一个job
        JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("MyJob", "MyJob_Group")
                                  .usingJobData("author", "认知科技技术团队").build();
        //使用jobDateMap
        job.getJobDataMap().put("微信公众号", "认知科技技术团队");

        //启动
        scheduler.start();
        //调度假如这个job
        scheduler.scheduleJob(job, trigger);
        TimeUnit.HOURS.sleep(1);
        scheduler.shutdown(true);
    }

    public static class MyJob implements Job {

        @Override
        public void execute(JobExecutionContext jobExecutionContext) {
            System.out.println("hello begin  " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(20);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("hello end  " + Thread.currentThread().getName());
        }
    }
}

1、Java避坑指南:ScheduledThreadPoolExecutor避坑

2、Java避坑指南:ScheduledThreadPoolExecutor避坑之异常信息会丢失,任务不再继续被调度的源码分析

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档