I use Quartz scheduler for executing 10 jobs. All of these jobs have their own trigger. So they are executed asynchronously.
However now I need 2 of these jobs to be executed in more specific way. Lets say that Job1 is executed every even minute and Job2 every odd minute. Now I want Job2 to wait for Job1 to be finished.
Example: Job1 starts to execute at 10:02. At 10:03 Job2's trigger is fired. But before Job2 starts to execute, it will look at Job1 if it has finished.
I found annotation #DisallowConcurrentExecution for job class that implements Job interface. I thought that this will do the thing, but then I read that it will only disallow concurrent execution of jobs with the same JobKey(name,group). But I cant have the same JobKey for my jobs. So this annnotation is good for just one job I guess.
Do you have some idea how I can solve my issue? Many thanks.
Check the details of existing running job with this call and take appropriate action..
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
Refer this Jobs status
You can define a static variable to mark Job1 finished or not. When you create Job2, in your code, you can check the static variable before execute.
Related
Basically, I am using an implementation of Quartz Scheduler and I want multiple jobs to run at the same time but some should run before the others. For this, I have found the parameter "priority" for a Trigger.
SO let's say I have 4 jobs, each with its own trigger. I set the priorities like this:
job1 - priority 5
job2 - priority 3
job3 - priority 11
job4 - priority 8
I want them to be run in this order: job3, job4, job,1, job2
Out of 20 runs, only around 3 times I get the expected result. For the others, the first task to be run is pretty much random, and the rest are ordered correctly. One run would be like: job1, job3, job4, job2 OR job4, job3, job1, job2
Am I not understanding properly how priorities work in Quartz? I can't find exactly what is happening.
The issue here is that Quartz doesn't ensure that when you schedule multiple jobs at the same time with different priorities, you will get them in the order you want UNLESS you have the working thread already busy. Otherwise, if the working thread is not busy, it will pick up the job with the highest priority that you could schedule in the span of nanoseconds.
For my case, the thread was not busy so while I was scheduling all the jobs, quartz had time to pick up and process the first job I scheduled. The rest of the jobs had time to be scheduled while the thread was busy processing job1.
You guys can follow the message "batch aquisition of..." in order to track down the problem yourselves.
My solution is to use the method schedule for a List of jobs.
I have a job that runs every 2 minutes:
org.quartz.CronScheduleBuilder.cronSchedule("0 0/2 * * * ?").withMisfireHandlingInstructionDoNothing()
Currently, if the job takes more than 2 minutes, Quartz waits another 2 minutes to run it again.
How do I start it right away if it took more than the scheduled interval?
I do not want Quartz to create another job and run both concurrently, because in case the job always fails, I don't want to fill the job queue up, I want the job to run with at least a 2 minute interval.
Misfire instructions tell Quartz what to do when a job runs late.
If a job didn't fire on time because the scheduler was down, or because the previous run took longer than expected, or any other cause, that's a misfire. And you can use misfire instructions like withMisfireHandlingInstructionDoNothing() to tell Quartz what to do.
In this case, you're telling Quartz: "If this job takes longer than expected, that is my problem, not yours. Don't fire up another instance concurrently, don't wait for it to finish. Ignore it. Do nothing".
If you want to change this, you can use a different misfire instruction, like withMisfireHandlingInstructionFireAndProceed(), which will instruct Quartz to fire a misfired job as soon as the previous one finishes.
You can look up available misfire instructions for each type of schedule in the API Javadoc.
I have a task that is scheduled periodically. Sometime it can take longer than expected.
I am trying to find a way to make sure that scheduling will be canceled in case the task is already running. All mechanisms I check will make the task wait and run it after the first finish
locking ofcourse will do the job but I'm looking of something more high level
Any Idea
You can use ScheduledExecutorService. scheduleAtFixedRate is probably what you want as it will wait for your tasks to finish, iff one takes longer than the rate you specify:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
Example:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
// Body will be executed every second unless the previous task hasn't finished.
}, 0L, 1L, TimeUnit.SECONDS);
There is something called scheduleAtFixedRate and scheduleAtFixedDelay.
scheduleAtFixedRate will start another process at defined time, so if previous process is not completed, two processes will be running and it might cause race condition of running same thing twice.
scheduleAtFixedDelay will start after fixed time once a task is completed.
scheduleAtFixedRate vs scheduleWithFixedDelay
In Spring you can do this by using annotation:-
#Scheduled(fixedDelay =30000)
http://howtodoinjava.com/spring/spring-core/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/
do you know Apache Camel framework?
It has a module called quartz2 and has a much possibility to scheduling any task.
try read this page:
http://camel.apache.org/quartz2.html
I'm pretty new to Quartz and I've come a cross the following requirement:
I need to create a scheduler that schedules single job that each time it ends it rescheduled but with calculated interval time.
For example:
1. Start job that ends after 15minutes, then when finished reschedule it to end after 1Hour, when finished reschedule it to end after 45 minutes...and so on...
The point is that when job finishes I dynamically calculate the next interval and need to fire the event again.
How to accomplish that with Quartz?
Thanks.
Provided you can trigger it explicitly for the first time, something like
scheduler.addJob(jobDetail, true);
scheduler.triggerJob(jobName, groupName); //(1)
and code the job class such a way that after its main work is done, calculate the next trigger time and schedule it before job exits. Something like
scheduler.scheduleJob(jobDetail, trigger); //(2)
Note that the the job trigger in code snippet (1) removes the job after its done. That means you will have to schedule it, in (2), as if its a new job as far as scheduler is concerned.
I need to implement a Quartz job that behaves differently depending on how many times it has been run.
What would you say is the best (or at least a good) way to do that ?
Keeping a counter as state doesn't seem to work since it looks like Quartz recreates it's jobs every time.
Thanks.
This is what the Quartz PersistJobDataAfterExecution annotation allows you to easily implement without using any extra framework / logic.
From PersistJobDataAfterExecution (Quartz 2.2.0) javadoc:
An annotation that marks a Job class as one that makes updates to its
JobDataMap during execution, and wishes the scheduler to re-store the
JobDataMap when execution completes.
So when your job starts you simply read your job execution counter from the JobDataMap that is passed to the job's execute method. If the counter is not present in the JobDataMap, you initialize it with 0. At the end of your job execution you increment the counter in the JobDataMap. This updated counter value will then be available during the next job execution.