I am trying to create a Timer/TimerTask that will run the same day of every month. I can't schedule a repeating Timer because a month won't always be the same lenght of time.
So, here is my solution:
public class MyTask extends TimerTask {
public void run(){
//do process file stuff
if(scheduledExecutionTime() != 0){
TimerHelper.restartMyTimer();
}
}
}
public class TimerHelper {
public static HashTable timersTable = new HashTable();
public static void restartMyTimer(){
Calendar runDate = Calendar.getInstance();
runDate.set(Calendar.DAY_OF_MONTH, 1);
runDate.set(Calendar.HOUR_OF_DAY, 4);
runDate.set(Calendar.MINUTE, 0);
runDate.add(Calendar.MONTH, 1);//set to next month
MyTask myTask = new MyTask();
Timer myTimer = new Timer();
myTimer.schedule(myTask, runDate.getTime());
timersTable = new HashTable();//keeping a reference to the timer so we
timersTable.put("1", myTimer);//have the option to cancel it later
}
}
The problem I think I'm going to run into is that because the first TimerTask creates the second Timer, will the first Timer be kept around because it created the second? After the code finishes on the first Timer, will that thread and object be taken care of by garbage collection? Over time I don't want to build up a bunch of Threads that aren't doing anything but aren't being removed. Maybe I don't have a proper understanding of how Threads and Timers work...
I'm open to suggestions of other ways to create a monthly timer as long as I don't have to use third party JARs.
Thanks!
If what worries you is to create unneeded objects you can alway create an object which in turn creates/"destroy" all the references, so the objects created may be gc'ed.
In the worst case, you'll have 12 unneeded objects in a year, which, I think is bearable. Still your concern is valid.
Here's my attempt following Joel's suggestion of schedule at the end of the execution. Notice, the current Timer is replaced by a new one, so, both, the timer and the timer task could be gc'ed.
I would suggest simply using Quartz and scheduling jobs via a CronTrigger which will allow you to specify you want the job executed on the first day-of-the-month, and let Quartz handle the timing logic.
Here is a further code example of how to use CronTrigger.
Quartz is a dead-simple easy library to use.
the simplest solution might be to use cron or equivalent to schedule a stand-alone program execution...
The Quartz scheduler library allows you to schedule based on cron job expressions.
Why do you need to recreate Timer every time? Timer is just thread with glue code around. Cancelling it cause terminating of other tasks running on that Timer.
It is better to use the following:
TimerTaskWithCallback just executes MonthlyTimer.taskCallback after original task execution. Could have "try { } catch {} finally {}" glue code.
What about just using a scheduled timer, and as you complete the currently scheduled task schedule the next:
You can use JodaTime to do the date calculations more easily.