I am looking for a solution to start and stop a program at predefined time intervals.
A scheduler would do the required justice, but how could the same be attained without using a scheduler.
I could always write a block of code, which checks for the current timings and based on this i could make a decision, however executing this piece of code would consume additional resources and processing power, which is not required if the program runs for hours.
Any efficient suggestions/solution on how this could be attained?
You can use a timer with following algorithm.
in timer.tick Method
Stop Timer
Perform Operation
Start Timer
In Form Load
Set Timer interval
Set Timer Tick
This works with Winforms
You wish to start and stop a program. If by program you mean an entire Java process I suggest that you use crontab for Linux/Unix to define the timing and then invoke some start- and stop-script. Windows has similar capabilities by the use of the Task Scheduler.
Crontab example that starts a job at 11 and 16 every day.
00 11,16 * * * /home/someuser/bin/start-app.sh
If you wish to start a job from within a Java process I suggest that you use a Timer and schedule a TimerTask that does the job for you.
However, I guess that both of the solutions above are technically schedulers that you did not want to use.
Related
I would like to schedule a periodic task which executes every X hours. I have a service which is written in Java and I was thinking of creating a long running background thread that runs forever as long as the service is up. How can I ensure that we are executing the task once every X hours? Is clock drift on my host an issue I should be worried about? I know that frequency of the clock ticks may change if the CPUs are working hard.
Edit: I was thinking of adding a bean to my spring configuration to spin up the thread which will periodically perform my task.
Java provides a java.util.Timer class that is designed to execute a task on a background thread. One of the modes of operation is "repeated execution at regular intervals". There are fixed-delay and fixed-rate execution methods that can be used, depending on your exact needs.
Java 5 added a java.util.concurrent.ScheduledThreadPoolExecutor class that is more flexible than Timer, but also offers fixed-delay and fixed-rate execution methods.
If you need such precise timing that these aren't suitable, I'm not sure that Java is an appropriate solution. You would be starting to enter the realm of a real-time system. At this point, you should likely be looking for other options.
If you are worried, write a test process and run it on the target platform. Using the feature you plan to use for the real process (like ScheduledExecutorService), schedule a task to log the host time every 24 hours. If the host doesn't use NTP to keep its clock synchronized, perhaps you could also make call to a time-keeping web service and log that too. After a few days, you should have a good sense of whether you need a method to correct for drift.
My guess is that the built-in scheduler will be accurate to less than a second per day.
Is clock drift on my host an issue I should be worried about?
Yes, clock drift can be an issue when using ScheduledThreadPoolExecutor.
CronScheduler is specifically designed to be proof against clock drift.
Example usage:
Duration syncPeriod = Duration.ofMinutes(1);
CronScheduler cron = CronScheduler.create(syncPeriod);
// If you need just precisely "once every X hours", irrespective of the
// starting time
cron.scheduleAtFixedRate(0, X, TimeUnit.HOURS, runTimeMillis -> {
// Do the task
});
// If you need "once every X hours" in terms of wall clock time,
// in some time zone:
ZoneId myTZ = ZoneId.systemDefault();
cron.scheduleAtRoundTimesInDay(Duration.ofHours(X), myTZ, runTimeMillis -> {
// Do the task
});
See Javadocs for scheduleAtRoundTimesInDay.
According to this Google article,
"You can also use the Task Queue to do the write at a later time, which has the added benefit that the Task Queue automatically retries failures."
Suppose I'm trying to keep my daily spend on Google App Engine under a certain budget. Let's say I start to detect I'm getting low on quota for the day so I want to reschedule the work for tomorrow. It would be great to use Task Queues for this instead of Cron jobs because the initiation of the work and the rescheduling of the work can be handled pretty similarly.
How do I put a task on the Task Queue and specify that it should not begin until a particular time? I can see how I might use RetryOptions to get part of what I want, namely to delay the work. But RetryOptions doesn't seem to provide a way to specify not to retry until 24 hours have passed since "now" or don't retry until midnight.
Thanks for your help.
Looks like I can use TaskOptions.countdownMillis(long) to specify how long to wait before executing the task.
The documentation says "later time", in the sense that your application doesn't stop to wait for your write to go through, so you work in parallel.
If you want to control WHEN to start a cleanup or something similar, look into CRON jobs
I am trying to find the better way to update my database.
I have two solution but I don't know which is the less demanding.
The first one is to create a java program with a Thread.sleep and an infinite loop.
The second way is always with a java program but no thread sleep and infinite loop, just the update program and I execute this program using cron.
Thanks for your help
"No thread sleep" + cron is simpler and easier to maintain:
Your program does just one main thing - updates the database.
Scheduling is delegated to cron. You are more flexible in configuration and do not need to write extra code to support "scheduling"
I have an application that checks a resource on the internet for new mails. If there is are new mails it does some processing on them. This means that depending on the amount of mails it might take just a few seconds to hours of processing.
Now the object/program that does the processing is already a singleton. So right now I already took care of there really only being 1 instance that's handling the checking and processing.
However I only have it running once now and I'd like to have it continuously running, checking for new mails more or less every 10 minutes or so to handle them in a timely manner.
I understand I can take care of this with Timer/Timertask or even better I found a resource here: http://www.ibm.com/developerworks/java/library/j-schedule/index.html that uses Scheduler/SchedulerTask. But what I am afraid of.. is if I set it to run every 10 minutes and a previous session is already processing data it will put the new task in a stack waiting to be executed once the previous one is done. So what I'm afraid of is for instance the first run running for 5 hours and then, because it was busy all the time, after that it will launch 5*6-1=29 runs immediately after each other checking for mails and/do some processing without giving the server a break.
Does anyone know how I can solve this?
P.S. the way I have my application set up right now is I'm using a Java Servlet on my tomcat server that's launched upon server start where it creates a Singleton instance of my main program, then calls some method to do the fetching/processing. And what I want is to repeat that fetching/processing every "x" amount of time (10 minutes or so), making sure that really only 1 instance is doing this and that really after each run 10 minutes or so are given to rest.
Actually, Timer + TimerTask can deal with this pretty cleanly. If you schedule something with Timer.scheduleAtFixedRate() You will notice that the docs say that it will attempt to "make up" late events to maintain the long-term period of execution. However, this can be overcome by using TimerTask.scheduledExecutionTime(). The example therein lets you figure out if the task is too tardy to run, and you can just return instead of doing anything. This will, in effect, "clear the queue" of TimerTask.
Of note: TimerTask uses a single thread to execute, so it won't spawn two copies of your task side-by-side.
On the side note part, you don't have to process all 10k emails in the queue in a single run. I would suggest processing for a fixed amount of time using TimerTask.scheduledExecutionTime() to figure out how long you have, then returning. That keeps your process more limber, cleans up the stack between runs, and if you are doing aggregates, ensures that you don't have to rebuild too much data if, for example, the server is restarted in the middle of the task. But this recommendation is based on generalities, since I don't know what you're doing in the task :)
hello there is something i've realized with quartz when working.Say a cron is set to wake up every 2min with the expression 0 0/2 * * * ? .
When you run the project at say 13:10:30, the first action happens at 13:12:00 and the second 13:14:00 and every 2min 0 second for the rest. Obviously between the startup of the project and the first occurence of the action there have been 1mn:30s only.
Is there a way to for the first occurrence to respect the 2min no matter which at seconds the project starts?
Cron jobs are configured in Quartz using the CronTrigger class. The alternative is to use SimpleTrigger, which you can construct using fixed delay intervals. SimpleTrigger has various constructors, allowing you to specify the start time, end time, number of repeats, repeat interval, and so on.
Having said that, I'd recommend against using Quartz for this kind of scheduling, and use java.util.concurrent.Executors.newScheduledThreadPool(). It's much easier than Quartz when it comes to simple repeating tasks.
Quartz may use cron for the scheduling, which is based on date and time, not duration. This means that the cron expression you define is directly related to the current time on the machine, not on when the application started.
I am not aware of a Quartz configuration that will help you to solve your problem. However, a solution is to create your own Thread, which started during the launch of your application and that basically waits 2 minutes before calling a method:
while (running) {
Thread.sleep(1000 * 120);
doStuff();
}