I'm trying to run a method once a week. For example, every Monday 8pm. I use this code:
Timer timer = new Timer();
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
Date time = calendar.getTime();
timer.schedule(new PrintTask(),
time);
// other code where variable gets increased
public class PrintTask extends TimerTask {
public void run() {
variable = 0;
}
}
However, if I am right, the dosomething code is run continuously - as long as the calendar time has already passed. For example, now it has already been Monday, so the dosomething code is run all the time. A variabele gets increased, but it must be reset to 0 on Monday. The variable is now constantly 0, because it is reset again and again. If I use calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);, the variable is not reset, because it has not been Sunday yet. But as soon as it is Sunday 8pm, he will probably continue to reset the rest of that day.
I want the dosomething code to be executed only once at the one time specified. Can someone tell me how to adjust the code to achieve this?
Sorry for my English
Please look at this question here(How i can run my TimerTask everyday 2 PM). It almost deals with same kind of problem.
Cancel the timer using the cancel api of Timer class, and reschedule the timer inside the run() method; this should prevent from updating the variable everytime.
The Timer class can be used to schedule things to run once, or multiple times. The way you are scheduling it at this moment will only make it once at the given time.
https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html#schedule(java.util.TimerTask,%20java.util.Date)
There are better options if you want to schedule tasks, for example the ScheduledExecutorService:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
According to Java Concurrency in Practice:
Timer can be sensitive to changes in the system clock, ScheduledThreadPoolExecutor isn't.
Timer has only one execution thread, so long-running task can delay other tasks. ScheduledThreadPoolExecutor can be configured with
any number of threads. Furthermore, you have full control over created
threads, if you want (by providing ThreadFactory).
Runtime exceptions thrown in TimerTask kill that one thread, thus making Timer dead :-( ... i.e. scheduled tasks will not run anymore.
ScheduledThreadExecutor not only catches runtime exceptions, but it
lets you handle them if you want (by overriding afterExecute method
from ThreadPoolExecutor). Task which threw exception will be canceled,
but other tasks will continue to run.
http://jcip.net/
Related
I have the following while loop:
while (keepRunning) {
if (!once) {
// Run a test method every 30th second
// Run the new calculations from the database
new CalculatorDriver().run();
// Wait in the while loop for 1 second before looping again
TimeUnit.SECONDS.sleep(1);
}
}
This while loop will loop every second through the code, but now I want to run a method called: getNewCalculations() every 30th second of a minute, so for example, the method needs to run at:
18:26:30
18:27:30
18:28:30
I already found a way to run a method every x seconds:
Timer timer = new Timer();
timer.schedule(new Task(), 60 * 1000);
But I also need to start it at a specific point. In C# someone tried this to run a script every 30th and every 0th second: https://stackoverflow.com/a/53846390/10673107.
I could just add an if where the second can't be equal to 0, but I was wondering if there was a better way to do this.
How can I run it only in the 30th second?
Set an initial delay by calculating the number of seconds to wait until the next 30th second is due to arrive. If the current moment is :10, wait 20 seconds. If the current moment is :56, wait 34 seconds.
The Duration class may help with that, along with ZonedDateTime class.
If you read the Javadoc for Timer/TimerTask you will learn those classes were supplanted years ago by the Executors framework that arrived in Java 5.
Use a ScheduledExecutorService to schedule a task to run after an initial delay specified by you. After the initial delay, specify a repeating period of one minute.
Your task will then be repeating on the 30th second mark of every minute. Know that this scheduling is approximate. The host OS, the JVM’s internal scheduler, and garbage-collection all impact when the task actually runs. So each run may vary.
Or, if you want to protect against any politician-imposed anomalies on your region’s time-keeping, schedule only a one-time scheduled task rather than repeating task. Pass to that task a reference to the ScheduledExecutorService object. The task can then schedule its own next run after running the initial-delay calculation again.
Be sure to eventually shutdown your executor service. Otherwise its backing pool of threads may continue to run indefinitely even after your app ends, like a zombie 🧟♂️.
Be aware that any exception or error bubbling up to the scheduled executor service will silently halt any further scheduling.
All of these topics have been addressed many times already on Stack Overflow. Search to learn more.
I have a Timer class that I want to schedule to run for 30 minutes and for it to execute every hour from Saturday at 12AM to Sunday at midnight.
How would I go about doing this?
Thanks.
The java.util.Timer class does not have the functionality to do this using repeated tasks:
You cannot configure a Timer to >>stop<< running repeated tasks at a given time
The execution model for repeated tasks is "fixed-delay execution"; i.e. a new task is scheduled based on the end-point of the previous task. That results in time slippage ... if tasks take a long time.
The simple solution is:
create a single Timer object
use schedule(TimerTask task, Date time) in a loop to schedule 48 separate tasks, starting on each hour in the range that you require.
According to the javadoc, Timer is scalable and should be able to cope with lots of scheduled tasks efficiently.
The above does not deal with the requirement that each task runs for 30 minutes. It is not clear what that actually means, but if you want the task to run for no more than 30 minutes, then you need to implement a "watch dog" that interrupts the thread running the task when its time is up. The task needs to be implemented to check for and/or handle thread interrupts appropriately.
You could have a loop run and in the loop just sleep for an hour or however long you wanted. Would something like this work?
for(int i = 0; i < 24; i++) {
// do whatever you want to do
try {
// Sleep for an hour
Thread.sleep(6000000);
catch(InterruptedException e) {
e.printStackTrace();
}
}
I might have misunderstood the question... but if that's what you wanted.. then... yay?
I want o make threads execute at specific exact times (for example at: 2012-07-11 13:12:24 and 2012-07-11 15:23:45)
I checked ScheduledExecutorService, but it only supports executing after specific period from the first run and I don't have any fixed periods, instead I have times from database to execute tasks on.
In a previous question for a different problem here, TimerTask was the solution, but obviuosly I can't make thread a TimerTask as Runnable and TimerTask both have the method run which needs to be implemented. The question here if I make the thread extends TimerTask and have one implementation of run(), would that work?
If not, then how it's possible to do what I'm trying to do?
Use TimerTask .
Create a TimerTask object with a field variable as your thread.
Call the Thread start from the Timer task Run method.
public class SampleTask extends TimerTask {
Thread myThreadObj;
SampleTask (Thread t){
this.myThreadObj=t;
}
public void run() {
myThreadObj.start();
}
}
Configure it like this.
Timer timer new Timer();
Thread myThread= // Your thread
Calendar date = Calendar.getInstance();
date.set(
Calendar.DAY_OF_WEEK,
Calendar.SUNDAY
);
date.set(Calendar.HOUR, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
// Schedule to run every Sunday in midnight
timer.schedule(
new SampleTask (myThread),
date.getTime(),
1000 * 60 * 60 * 24 * 7
);
I think you should better use some library like the Quartz Scheduler. This is basically an implementation of cron for Java.
Have you looked at CountDownLatch from the java.util.concurrent package? It provides a count down then triggers the thread(s) to run. I never needed to use it myself, but have seen it in use a couple times.
How do you activate or run a loop every tenth of a second? I want to run some script after an amount of time has passed.
Run a script every second or something like that. (notice the bolded font on every)
You can use a TimerTask. e.g.
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
You simply need to define a Runnable. You don't have to worry about defining/scheduling threads etc. See the Timer Javadoc for more info/options (and Quartz if you want much more complexity and flexibility)
Since Java 1.5:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new RepeatedTask(), 0, 100, TimeUnit.MILLISECONDS);
and
private class RepeatedTask implements Runnable {
#Override
public void run() {
// do something here
}
}
(remember to shotdown() your executor when finished)
You sleep.
Check out Thread.sleep() but be warned that you probably really don't want your whole program to sleep, so you might wish to create a thread to explicitly contain the loop and it's sleeping behavior.
Note that sleep only delays for a number of milliseconds; and, that number is not a perfect guarantee. If you need better time resolution you will have to use System.currentTimeMillis() and do the "time math" yourself. The most typical scenario is when you run something and you want it to run ever minute. The time the script runs must be captured by grabbing System.currentTimeMillis() before and after the script, and then you would need to sleep the remaining 1000 - scriptRunTime milliseconds.
I am using Timertask in my web application to launch a background thread once every 24 hrs every day at midnight. So I have a ServletContextListener and in contextInitialized, I create a Timertask object timertask(say) and a Timer object say t.
I call
t.schedule(timertask, firstTime.getTime(), rescheduleMiliSec);
where firstTime.getTime() = midnight and rescheduleMiliSec = 24 hr.
The thread launches fine and does what it is supposed to do in DIT.Every 24 hrs it launches the background task.
When it moves to PROD, the thread runs only once when context is initialised but not after that.
Is there any specific setting that might be the cause for this?
Is it possible your TimerTask implementation is throwing a RuntimeException?
If not an exception, then some TimerTask being scheduled in that Timer is blocking indefinitely. Those are the only two conditions that I am aware of that could cause a Timer to fail.
BTW, you might want to look into a ScheduledExecutorService. That is the more modern way of scheduling tasks.
I think the reason is simple but it may evade the naked eye.
firstTime.getTime()
is in milliseconds and the following method take precedence:
schedule(TimerTask task, long delay, long period)
insead of the intended:
schedule(TimerTask task, Date firstTime, long period)
In the contextInitialized method after scheduling a task using TimerTask , is there any code below that , may be that is causing an exception.