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.
Related
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 am using Quartz for scheduling parallel tasks, How can I get job running time in Quartz?
JobExecutionContext expose a some useful methods:
getJobRunTime: returns the time only after the job has actually completed
(you may want to use a JobListener to call it when job finished the
execution).
getFireTime: get the actual time the job started, so you can the current Date to calculate the elapsed time (you can call this method even inside the Job itself).
Note: To know "how long it WILL takes to run one job" you have to implement on your own doing some simple math to get the % of completion. Quartz itself doesn't have such a feature.
ScheduledExecutorService seems to have the problem that if it can't get a free thread the periodic task will happen with delay. Unfortunately for me, the periodic task it's assigned to really does need to happen fairly on schedule. At present it's scheduled for once per minute but sometimes due to the application being busy with other things (I assume this is why) it fails to make it within five minutes, and five minutes happens to be the "major production bugs" threshold.
How to force this via prioritizing or otherwise controlling the thread balancer?
If your ScheduledExecutorService is used for other tasks or if your task sometimes takes more than 1 minute to run, you can simply increase the number of threads available in your ScheduledExecutorService. So if one task has not finished running, the executor will still be able to run a new one.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
(I picked 10 randomly - if you run your task every minute and it can run for up to 5 minutes, that leaves you some margin for error)
I have a sort of complex problem like below.
- we have a real time system with large number threads requirement. In order to optimize the performance, we are thinking of following design.
create a thread pool executor with max number of threads
each thread is used to create scheduled executor service.
now the tasks are being assigned to these executor services evenly based on load
BUT the biggest problem is, if one of the task in the queue contains a sleep (for few secs), it blocks the corresponding Schedule executor service thread for that duration and subsequently all the following tasks in that queue.
In this regard, please suggest me how to suspend the execution of the task with sleep OR overriding the sleep somehow and rejoin/schedule the task again to the queue.
Thanks in advance
Seshu
Assuming I understand your question, your Schedule Executor service threads have a deadline requirement, but the actual workers can sleep for an unknown length of time, possibly throwing off the timing of the Schedule Executors. From your description I'm guessing what you want is for a task that needs to sleep to actually stop, save progress information and then requeue itself for the remainder of the work to be rescheduled at some future time. You'd have to build this into your application architecture.
Alternatively, you could have the scheduler threads launch the worker tasks in their own separate threads, letting them sleep as necessary, with one scheduler thread collecting all the worker terminations.
To get a better answer you're going to have to provide more information about what you're trying to accomplish.
Tasks which sleep are inherently unfriendly for running in any kind of bounded thread pool. The sleep is explicitly telling the thread that it must do nothing for a period of time.
If possible, split the task into 2 (or more parts), eliminating the sleep completely. Get the first half-task to schedule the second task with an appropriate delay.
Failing that, you could consider increasing the size of your thread pool somewhat - either setting a much larger cap to its size, or possibly even eliminating the cap altogether (not recommended for a server than might end up with many clients).
Alternatively, move the tasks with sleep statements in them into their own Scheduled executor. Then, they'll delay each other, but better-behaved tasks, with no wait statements in them, will get preferential treatment.