简体   繁体   中英

Java Quartz Scheduler - getScheduledFireTime returning incorrect value

I have the following sample Quartz job which retrieves a web page.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

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

public class SampleQuartzJob implements Job {

    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println(context.getJobDetail().getKey().toString() + " started");
        System.out.println("Scheduled fire time: " + context.getScheduledFireTime());
        System.out.println("Fire time: " + context.getFireTime());

        try {
            sendGet();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(context.getJobDetail().getKey().toString() + " completed");

        System.out.println();
    }

    private void sendGet() throws Exception {
        String url = "https://www.google.com/search?q=abc";

        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
    }

}

Following is the main class which creates 5 jobs and schedules them to run once every 5 seconds.

import static org.quartz.JobBuilder.newJob;

import javax.xml.bind.JAXBException;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzMainClass {

    public void init() throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        for (int i = 1; i <= 5; i++) {
            JobDetail job = newJob(SampleQuartzJob.class).withIdentity("Job " + i).build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

            scheduler.scheduleJob(job, trigger);

        }

        scheduler.start();

    }

    public static void main(String[] args) throws JAXBException, SchedulerException {
        QuartzMainClass quartzMainClass = new QuartzMainClass();
        quartzMainClass.init();
    }
}

I am using thread count of 1

org.quartz.threadPool.threadCount=1

    System.out.println("Scheduled fire time: " + context.getScheduledFireTime());

should be printing the scheduled times something similar to the following:

12:00:00 // for job 1
12:00:00 // for job 2
..
12:00:00 // for job 5

12:00:05 // for job 1
12:00:05 // for job 2
..
12:00:05 // for job 5

I am getting the expected output at times. But sometimes, the scheduledFireTime that is getting printed is incorrect. It is off the correct time by few seconds. Is something wrong with the code that I am using?

I've noticed this issue as well. This happens if your scheduler is getting overwhelmed by the number of jobs it needs to fire and starts misfiring.

I don't know why it gives incorrect date as it shouldn't. The work around I found was to fetch the trigger object from context object and get start date from it. That worked fine in such cases.

ctx.getTrigger() where .getTrigger is a function of org.quartz.JobExecutionContext Package. Fetch start-date from that trigger object and you'll get the correct datetime irrespective of scheduler misfiring or not.

  1. Look at the javadoc of

    getScheduledFireTime

  2. Your job is pretty heavyweight and yet you have 5 of them scheduled to start every 5 seconds each, having only 1 thread for Quartz. It can choke Quartz

you can simply upgrading your pool number thread, because Scheduled work on single thread.

you can implements this solution:

@Configuration
public class SchedulingConfigurerConfiguration implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(100);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);
    }
}


or by upgriding pool thread in your properties file or yml file:
spring.task.scheduling.pool.size=20 (20 is just an example)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM