定时任务调度框架Quartz--集群下的JOB与Trigger操作


SpringBoot下,使用集群配置Quartz链接: 定时任务调度框架Quartz–SpringBoot使用Quartz并使用集群配置

核心操作

创建一个任务

        创建一个任务非常简单,就是根据JOB接口实现类生成一个CronTrigger或者SImpleTrigger,并同时创建一个JobDetail,交给Scheduler调度器即可。具体实现代码完全可以参照CronTrggerSimpleTrigger

        第一种方案这里需要注意的是,在创建JobDetail的时候,可以增加一个Boolean属性storeDurably,true表明是否该JobDetail在没有任何Trigger与之关联的时候,还存放在数据库中。

    JobDetail jobDetail = newJob(clazz)
                    .withIdentity(param.getName(), param.getGroup())
                    .withDescription(param.getDescription())
                    .usingJobData(new JobDataMap())
                    //没有Trigger与之相关联也会存放在数据库中
                    .storeDurably()
                    .build();
                    
    //入库,方便下一步Trigger与该JobDetail绑定
    scheduler.addJob(jobDetail, false);
    
    //创建CronTrigger,失火策略使用错过不处理
    Trigger cronTrigger = newTrigger()
                    .withIdentity(param.getName(), param.getGroup())
                    .withSchedule(
                           cronSchedule(param.getCron())
                           .withMisfireHandlingInstructionDoNothing()                              
                    )
                    .withDescription(param.getDescription())
                    .forJob(jobDetail)
                    .build();
                    
     scheduler.scheduleJob(cronTrigger);

        第二种方案分别创建CronTriger与JobDetail。然后一次性交给schedule调度器加入调度进程。如果此时在调用一次scheduler.scheduleJob(job,otherTrigger),则会报错。因为Job已经加入到了Schedule调度中,不能重复加入。

    @Autowird
    private SchedulerFactoryBean schedulerFactoryBean;

    public boolean addDynamicScheduleJob(JobParam param) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(param.getName(), param.getGroup());
            if (scheduler.getTrigger(triggerKey) == null) {
                //实现了Job接口的类
                Class clazz = org.apache.commons.lang3.ClassUtils.getClass(param.getClassName());
                if (Job.class.isAssignableFrom(clazz)) {
                    //创建CronTrigger,失火策略使用错过不处理
                    Trigger cronTrigger = newTrigger()
                            .withIdentity(param.getName(), param.getGroup())
                            .withSchedule(
                                    cronSchedule(param.getCron())
                                            .withMisfireHandlingInstructionDoNothing()
                            )
                            .withDescription(param.getDescription())
                            .build();

                    //通过Job实现类创建JobDetail
                    JobDetail jobDetail = newJob(clazz)
                            .withIdentity(param.getName(), param.getGroup())
                            .withDescription(param.getDescription())
                            .usingJobData(new JobDataMap())
                            .build();

                    scheduler.scheduleJob(jobDetail, cronTrigger);

                    return Boolean.TRUE;
                } else {
                    throw new IllegalArgumentException("class类必须实现Job接口");
                }
            }
        } catch (Exception e) {
            LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
        }
        return Boolean.FALSE;
    }
	
	@Data
	public class JobParam {
	    private String name;
	    private String cron;
	    private String group;
	    private String className;
	    private String description;
	}
删除一个任务

        其实从作者的注释上来看,如果直接删除Job,那么与之关联的所有Trigger会连带删除。

public interface Scheduler ...
    /**
     * Delete the identified <code>Job</code> from the Scheduler - and any
     * associated <code>Trigger</code>s.
     * 
     * @return true if the Job was found and deleted.
     * @throws SchedulerException
     *           if there is an internal Scheduler error.
     */
    boolean deleteJob(JobKey jobKey)
        throws SchedulerException;

        另外一个删除方法是删除Trigger,如果此Trigger关联到的Job没有其他Trigger,那么Job也会被删除。

public interface Scheduler ...
    /**
     * Remove the indicated <code>{@link Trigger}</code> from the scheduler.
     * 
     * <p>If the related job does not have any other triggers, and the job is
     * not durable, then the job will also be deleted.</p>
     */
    boolean unscheduleJob(TriggerKey triggerKey)
        throws SchedulerException;

        一般会按照下方的代码来删除Job与Trigger。先把Trigger暂停。并停止Trigger的调度。最后删除Job。Trigger与Job 一对多,所以先删除Trigger,再删除Job

    public void deleteScheduleByNameAndGroup(String name, String group) {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
            Trigger trigger = scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }

            JobKey jobKey = JobKey.jobKey(name, group);
            //暂停并不调度触发器
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            //删除任务
            scheduler.deleteJob(jobKey);
        } catch (Exception e) {
            LOGGER.error("an exception was occurred , caused by :{}", e.getMessage());
            throw new ScheduleRuntimeException(e);
        }
    }
修改一个任务

        修改一个任务很简单,就是通过JobKey删除以前的Trigger。然后再创建一个新的任务

  • 1)通过TriggerKey暂停Trigger调度
  • 2)通过TriggerKey删除Trigger
  • 3)通过JobKey删除JobDetail
  • 4)最后创建新的定时任务,代码参考创建定时任务。创建Trigger与JobDetail交给Scheduler
    @SneakyThrows
    public boolean reloadSchedule(JobParam job) {
        //原来的的Job标识
        JobKey jobKey = JobKey.jobKey(job.getSourceName(), job.getSourceGroup()); 
        //新得Job标识
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getSourceName(), job.getSourceGroup());

        //删除原来的Trigger
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        Trigger trigger = scheduler.getTrigger(triggerKey);
        if (trigger != null) {
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.deleteJob(jobKey);
        }
        return this.addDynamicScheduleJob(job);
    }
暂停一个任务

        暂停一个定时任务很简单,只需要知道这个任务的name与group即可。从作者的注释来看,让一个JobDetail暂停执行,实际上的实现方式就是让该JobDetail关联的所有Trigger的运行状态改为暂停。

public interface Scheduler ...
    /**
     * Pause the <code>{@link org.quartz.JobDetail}</code> with the given
     * key - by pausing all of its current <code>Trigger</code>s.
     * 
     * @see #resumeJob(JobKey)
     */
    void pauseJob(JobKey jobKey)
        throws SchedulerException;

        我把测试的两个Trigger关联了同一个JobDetail,然后调用上述的Scheduler.pauseJob(Jobkey)方法,在QRTZ_TRIGGER表中发现TRIGGER_STATE的状态已经修改为PASUED
在这里插入图片描述

恢复一个任务

        同样得,恢复一个JobDetail也有两种操作:唤醒Trigger与唤醒JobDetail

        下面是通过JobKey恢复任务的源代码。通过JobKey唤醒此JobDetail关联的所有Trigger,并且触发Trigger们的失火策略。

public interface Scheduler ...
    /**
     * Resume (un-pause) the <code>{@link org.quartz.JobDetail}</code> with
     * the given key.
     * 
     * <p>
     * If any of the <code>Job</code>'s<code>Trigger</code> s missed one
     * or more fire-times, then the <code>Trigger</code>'s misfire
     * instruction will be applied.
     * </p>
     * 
     * @see #pauseJob(JobKey)
     */
    void resumeJob(JobKey jobKey)
        throws SchedulerException;

        下面是通过TriggerKey恢复任务的源代码。通过TriggerKey唤醒此Trigger,从而让该Trigger开始调度它所关联的JobDetail,同时触发该Trigge的r失火策略。

public interface Scheduler ...
    /**
     * Resume (un-pause) the <code>{@link Trigger}</code> with the given
     * key.
     * 
     * <p>
     * If the <code>Trigger</code> missed one or more fire-times, then the
     * <code>Trigger</code>'s misfire instruction will be applied.
     * </p>
     * 
     * @see #pauseTrigger(TriggerKey)
     */
    void resumeTrigger(TriggerKey triggerKey)
        throws SchedulerException;
立即执行任务

        立即执行一个任务。从源代码上来看,它创建了一个临时的新的Trigger来安排这次执行任务。不会影响到已经创建并存放在数据库中的Trigger。

public interface Scheduler ...
    /**
     * Trigger the identified <code>{@link org.quartz.JobDetail}</code>
     * (execute it now).
     */
    void triggerJob(JobKey jobKey)
        throws SchedulerException;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小大宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值