关于quartz定时器的使用和复用的问题

这几天在做项目,需要用到定时器的功能,所以搜索了一下怎么写定时器,觉得quartz是一款简单易上手的,就是用了这个方式

首先必要的jar包必须要引入,

写一个TimedJob类去继承Job,重写里面的唯一的方法execute,就是你需要定时工作的内容,

如果需要传参,可以使用的方式:

(1)JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String time = jobDataMap.getString("time");

(2) private String orderId;

  public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

这两种方式都可以获取需要传的参数;

import java.util.Date;
import net.sf.json.JSONObject;
import org.hamcrest.core.IsNot;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TimedJob implements Job{
    /*
     * 需要被执行的定时任务类
     * */
    private String orderId;//
    private String msg;
    
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("定时器工作");
        /*JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String time = jobDataMap.getString("time");*/
        
        System.out.println("orderid:"+orderId+new Date());
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }
}

然后写一个TimeManager管理配置这个定时工作的任务
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

public class TimeManager {
    /*
     * 配置需要执行的方法类
     * */
    public void go(String orderId) throws Exception {
        // 首先,必需要取得一个Scheduler的引用
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();
        //jobs可以在scheduled的sched.start()方法前被调用
        
        //job 1将每2分钟执行一次(在该分钟的第15秒)
        JobDetail job = newJob(TimedJob.class).withIdentity("job1", "group1").usingJobData("orderId", orderId).build();
        CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("15 0/1 * * * ?")).build();
        Date ft = sched.scheduleJob(job, trigger);
        //System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: " +

        // 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入N个Job
      sched.start();
      
        try {
            //主线程等待一分钟
            Thread.sleep(60L * 1000L);
        } catch (Exception e) {}    
       //关闭定时调度,定时器不再工作
       sched.shutdown(true);
}

}


这个定时器写好后我的模块确实可以正常工作了,但是同时也需要使用我的方法的时候发现调用定时器出问题,不能同时调用两个定时器,

我就在想我的定时器是不是并行任务,于是了解到未做处理的quartz定时器默认就是并行的,所以一时间没有找到究竟错在了哪里

后来请教了一下老员工,

JobDetail job = newJob(TimedJob.class).withIdentity("job1", "group1").usingJobData("orderId", orderId).build();

因为我作为识别的定时器任务配置的都是job1,trigger1,所以在复用的情况下再次调用的时候其实我的job1和trigger1已经开启了,所以无法调用,

这个时候为了提高代码的复用,和定时器的使用,所以就将job1和trigger1改成了不重复自动生成的哈希值代替就解决了定时器复用的问题

又在老员工的帮助下写了一个新的简单的方法,新写一个urtil类

public static void startJob(String jobName, String triggerName, String groupName, Class jobCLass, Date jobStartTime, Integer intervalHours, int repeatCount, Map<String, Object> params) throws SchedulerException {
        Scheduler scheduler = sf.getScheduler();
        JobBuilder jobBuilder = JobBuilder.newJob(jobCLass);
        if(params != null) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if(entry.getValue() instanceof Boolean) {
                    jobBuilder.usingJobData(entry.getKey(), (Boolean) entry.getValue());
                } else if(entry.getValue() instanceof Integer) {
                    jobBuilder.usingJobData(entry.getKey(), (Integer) entry.getValue());
                } else if(entry.getValue() instanceof Float) {
                    jobBuilder.usingJobData(entry.getKey(), (Float) entry.getValue());
                } else if(entry.getValue() instanceof Long) {
                    jobBuilder.usingJobData(entry.getKey(), (Long) entry.getValue());
                } else if(entry.getValue() instanceof Double) {
                    jobBuilder.usingJobData(entry.getKey(), (Double) entry.getValue());
                } else {
                    jobBuilder.usingJobData(entry.getKey(), entry.getValue().toString());
                }
                
            }
        }
        if (StringUtils.isNotEmpty(jobName) && StringUtils.isNotEmpty(groupName)) {
            jobBuilder.withIdentity(jobName, groupName);
        }
        JobDetail jobDetail = jobBuilder.build();
        TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
        if (StringUtils.isNotEmpty(triggerName) && StringUtils.isNotEmpty(groupName)) {
            triggerBuilder.withIdentity(triggerName, groupName);
        }
        if (jobStartTime == null) {
            triggerBuilder.startNow();
        } else {
            triggerBuilder.startAt(jobStartTime);
        }
        Trigger trigger = triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule()
                                    .withIntervalInHours(intervalHours).withRepeatCount(repeatCount)).build();
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();
    }

一起解决了传值问题和配置问题,使用起来更加方便了

然后我就将我的TimeManager类中的go方法吧之前的都删了就换成了下面这句

QuartzManageUtils.startJob(DateUtil.getCurrentTimeZone(), DateUtil.getCurrentTimeZone(), "group1", TimedJob.class, DateUtil.addDay(new Date(), 0), 1, 1, params);

完全可以复用quartz定时器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值