Quartz---串行执行、JobDataMap持久化

1.Quartz串行执行

在Quartz中,作业(Job)默认是以并行方式执行的,这意味着如果调度器(Scheduler)有多个线程可用,并且满足触发条件,那么多个作业可能会同时执行。然而,有时候我们可能希望作业以串行方式执行,即一个接一个地执行,而不是同时执行。

实例

记录每个任务执行间隔

代码

package job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

import javax.xml.crypto.Data;
import java.util.Date;

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {
            Thread.sleep(2000);
            System.out.println("excute:"+new Date());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package schedule;

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

public class MySchedule {
    public static void main(String[] args) {
        // 创建作业详情
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)//作业的类名
                .withIdentity("myJob", "group1")//作业的身份标识(名称和组名)
                .build();
        //创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")//触发器的身份标识(名称和组名)
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()//设置触发器的调度计划
                        .withIntervalInSeconds(2)//设置作业执行的间隔时间为2秒。
                        .repeatForever())//指定触发器应该无限次地重复执行作业。
                .build();
        try {
            // 创建调度器实例
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            // 将作业和触发器注册到调度器
            scheduler.scheduleJob(jobDetail, trigger);
            // 开始调度
            scheduler.start();
        } catch (SchedulerException se) {
            se.printStackTrace();
        }
    }
}

执行结果

每个任务最少需要3秒完成,而任务执行间隔为2,说明任务调度是并发执行的

串行执行的两种方法

1.使用单个线程调度器


如果你只有一个线程用于执行作业,那么作业自然会串行执行。你可以通过配置线程池来实现这一点,确保线程池的大小为1。这样,在任何给定时间,只有一个作业能够被执行。

ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor(); threadPool.setCorePoolSize(1); threadPool.setMaxPoolSize(1); threadPool.setQueueCapacity(1); threadPool.setThreadNamePrefix("Quartz-Executor-"); threadPool.initialize(); SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.setThreadPool(threadPool); scheduler.start();

2.使用@DisallowConcurrentExecution注解
package job;

import org.quartz.*;

import javax.xml.crypto.Data;
import java.util.Date;
@DisallowConcurrentExecution
public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {
            Thread.sleep(3000);
            System.out.println("excute:"+new Date());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
3.结果

2.JobDataMap数据持久化(持久化到内存中)

实例

计算任务执行次数

代码

package job;

import org.quartz.*;

import java.util.Date;

@DisallowConcurrentExecution

public class MyJob2 implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {

            JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
            jobDataMap.put("count",jobDataMap.getInt("count")+1);
            System.out.println(jobDataMap.getInt("count")+"-"+new Date());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package schedule;

import job.MyJob;
import job.MyJob2;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class MySchedule2 {
    public static void main(String[] args) {
        Integer count=0;
        // 创建作业详情
        JobDetail jobDetail = JobBuilder.newJob(MyJob2.class)//作业的类名
                .withIdentity("myJob", "group1")//作业的身份标识(名称和组名)
                .usingJobData("count", count)
                .build();
        //创建触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")//触发器的身份标识(名称和组名)
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()//设置触发器的调度计划
                        .withIntervalInSeconds(1)//设置作业执行的间隔时间为2秒。
                        .repeatForever())//指定触发器应该无限次地重复执行作业。
                .build();
        try {
            // 创建调度器实例
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            // 将作业和触发器注册到调度器
            scheduler.scheduleJob(jobDetail, trigger);
            // 开始调度
            scheduler.start();
        } catch (SchedulerException se) {
            se.printStackTrace();
        }
    }
}

执行结果

原因分析

Quartz的作业在执行时使用的是触发时创建的JobDataMap的一个拷贝,因此作业中对JobDataMap的任何更改都不会影响到原始的JobDataMap,也不会在作业执行结束后保留下来每次任务调度都会使用新的实例。

解决方案

任务类子类添加@PersistJobDataAfterExecution注解,并在任务类中实现Job接口

执行结果

注意此 注解对trigger中的JobDataMap无效

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杜小白也想的美

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

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

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

打赏作者

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

抵扣说明:

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

余额充值