You are on page 1of 9

7/26/12 Scheduling recurring tasks in Java applications

English Sign in (or register)

Technical topics Evaluation software Community Events

Scheduling recurring tasks in Java applications


Introducing a simple generalisation of the Java language's Timer class

Tom White, Lead Java Developer, Kizoom

Summary: All manner of Java applications commonly need to schedule tasks for repeated execution. Enterprise applications need to schedule daily logging or
overnight batch processes. A J2SE or J2ME calendar application needs to schedule alarms for a user's appointments. However, the standard scheduling classes,
Timerand TimerTask, are not flexible enough to support the range of scheduling tasks typically required. In this article, Java developer Tom White shows you
how to build a simple, general scheduling framework for task execution conforming to an arbitrarily complex schedule.

Date: 04 Nov 2003


Level: Intermediate
PDF: A4 and Letter (41KB | 12 pages)Get Adobe® Reader®
Also available in: Japanese

Activity: 59452 views


Comments: 6 (View | Add comment - Sign in)

Average rating (205 votes)


Rate this article

The java.util.Timerand java.util.TimerTaskclasses, which I'll refer to collectively as the Java timer framework, make it easy for programmers to
schedule simple tasks. (Note that these classes are also available in J2ME.) Before this framework was introduced in the Java 2 SDK, Standard Edition, Version
1.3, developers had to write their own scheduler, which involved grappling with threads and the intricacies of the Object.wait()method. However, the Java
timer framework is not rich enough to meet the scheduling requirements of many applications. Even a task that needs repeating every day at the same time cannot
be directly scheduled using Timer, due to the time jumps that occur as daylight saving time comes and goes.

This article presents a scheduling framework that is a generalisation of Timerand TimerTaskto allow more flexible scheduling. The framework is very simple -- it
consists of two classes and an interface -- and it's easy to learn. If you're used to working with the Java timer framework, you should be able to pick up the
scheduling framework very quickly. (For more information about the Java timer framework, see Resources.)

Scheduling a one-shot task

The scheduling framework is built on top of the Java timer framework classes. Therefore, we'll first look at scheduling using these classes before I explain how the
scheduling framework is used and how it is implemented.

Imagine an egg timer that tells you when a number of minutes have elapsed (and therefore that your egg is cooked) by playing a sound. The code in Listing 1 forms
the basis for a simple egg timer written in the Java language:

Listing 1. EggTimer class

package org.tiling.scheduling.examples;

import java.util.Timer;
import java.util.TimerTask;

public class EggTimer {


private final Timer timer = new Timer();
private final int minutes;

public EggTimer(int minutes) {


this.minutes = minutes;
}

public void start() {


timer.schedule(new TimerTask() {
public void run() {
playSound();
timer.cancel();
}
private void playSound() {
System.out.println("Your egg is ready!");
// Start a new thread to play a sound...
}
}, minutes * 60 * 1000);
}

public static void main(String[] args) {


EggTimer eggTimer = new EggTimer(2);

www.ibm.com/developerworks/java/library/j-schedule/index.html 1/9
7/26/12 Scheduling recurring tasks in Java applications
eggTimer.start();
}

An EggTimerinstance owns a Timerinstance to provide the necessary scheduling. When the egg timer is started using the start()method, it schedules a
TimerTaskto execute after the specified number of minutes. When the time is up, the run()method on the TimerTaskis called behind the scenes by Timer,
which causes it to play a sound. The application then terminates after the timer is cancelled.

Scheduling a recurring task

Timerallows tasks to be scheduled for repeated execution by specifying a fixed rate of execution or a fixed delay between executions. However, there are many
applications that have more complex scheduling requirements. For example, an alarm clock that sounds a wake-up call every morning at the same time cannot
simply use a fixed rate schedule of 86400000 milliseconds (24 hours), because the alarm would be too late or early on the days the clocks go forward or
backward (if your time zone uses daylight saving time). The solution is to use calendar arithmetic to calculate the next scheduled occurrence of a daily event. This is
precisely what the scheduling framework supports. Consider the AlarmClockimplementation in Listing 2 (see Resources to download the source code for the
scheduling framework, as well as a JAR file containing the framework and examples):

Listing 2. AlarmClock class

package org.tiling.scheduling.examples;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.tiling.scheduling.Scheduler;
import org.tiling.scheduling.SchedulerTask;
import org.tiling.scheduling.examples.iterators.DailyIterator;

public class AlarmClock {

private final Scheduler scheduler = new Scheduler();


private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;

public AlarmClock(int hourOfDay, int minute, int second) {


this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
}

public void start() {


scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
System.out.println("Wake up! " +
"It's " + dateFormat.format(new Date()));
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}

public static void main(String[] args) {


AlarmClock alarmClock = new AlarmClock(7, 0, 0);
alarmClock.start();
}
}

Notice how similar the code is to the egg timer application. The AlarmClockinstance owns a Schedulerinstance (rather than a Timer) to provide the necessary
scheduling. When started, the alarm clock schedules a SchedulerTask(rather than a TimerTask) to play the alarm. And instead of scheduling the task for
execution after a fixed delay, the alarm clock uses a DailyIteratorclass to describe its schedule. In this case, it simply schedules the task at 7:00 AM every
day. Here is the output from a typical run:

Wake up! It's 24 Aug 2003 07:00:00.023


Wake up! It's 25 Aug 2003 07:00:00.001
Wake up! It's 26 Aug 2003 07:00:00.058
Wake up! It's 27 Aug 2003 07:00:00.015
Wake up! It's 28 Aug 2003 07:00:00.002
...

DailyIteratorimplements ScheduleIterator, an interface that specifies the scheduled execution times of a SchedulerTaskas a series of
java.util.Dateobjects. The next()method then iterates over the Dateobjects in chronological order. A return value of nullcauses the task to be cancelled
www.ibm.com/developerworks/java/library/j-schedule/index.html 2/9
7/26/12 Scheduling recurring tasks in Java applications
(that is, it will never be run again) -- indeed, an attempt to reschedule will cause an exception to be thrown. Listing 3 contains the ScheduleIteratorinterface:

Listing 3. ScheduleIterator interface

package org.tiling.scheduling;

import java.util.Date;

public interface ScheduleIterator {


public Date next();
}

DailyIterator's next()method returns Dateobjects that represent the same time each day (7:00 AM), as shown in Listing 4. So if you call next()on a
newly constructed DailyIteratorclass, you will get 7:00 AM of the day on or after the date passed into the constructor. Subsequent calls to next()will return
7:00 AM on subsequent days, repeating forever. To achieve this behavior DailyIteratoruses a java.util.Calendarinstance. The constructor sets up the
calendar so that the first invocation of next()returns the correct Datesimply by adding a day onto the calendar. Note that the code contains no explicit reference
to daylight saving time corrections; it doesn't need to because the Calendarimplementation (in this case GregorianCalendar) takes care of this.

Listing 4. DailyIterator class

package org.tiling.scheduling.examples.iterators;

import org.tiling.scheduling.ScheduleIterator;

import java.util.Calendar;
import java.util.Date;

/**
* A DailyIterator class returns a sequence of dates on subsequent days
* representing the same time each day.
*/
public class DailyIterator implements ScheduleIterator {
private final int hourOfDay, minute, second;
private final Calendar calendar = Calendar.getInstance();

public DailyIterator(int hourOfDay, int minute, int second) {


this(hourOfDay, minute, second, new Date());
}

public DailyIterator(int hourOfDay, int minute, int second, Date date) {


this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, 0);
if (!calendar.getTime().before(date)) {
calendar.add(Calendar.DATE, -1);
}
}

public Date next() {


calendar.add(Calendar.DATE, 1);
return calendar.getTime();
}

Implementing the scheduling framework

In the previous section, we learned how to use the scheduling framework and compared it with the Java timer framework. Next, I'll show you how the framework
is implemented. In addition to the ScheduleIteratorinterface shown in Listing 3, there are two other classes -- Schedulerand SchedulerTask-- that make
up the framework. These classes actually use Timerand TimerTaskunder the covers, since a schedule is really no more than a series of one-shot timers. Listings
5 and 6 show the source code for the two classes:

Listing 5. Scheduler

package org.tiling.scheduling;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

www.ibm.com/developerworks/java/library/j-schedule/index.html 3/9
7/26/12 Scheduling recurring tasks in Java applications
public class Scheduler {

class SchedulerTimerTask extends TimerTask {


private SchedulerTask schedulerTask;
private ScheduleIterator iterator;
public SchedulerTimerTask(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
this.schedulerTask = schedulerTask;
this.iterator = iterator;
}
public void run() {
schedulerTask.run();
reschedule(schedulerTask, iterator);
}
}

private final Timer timer = new Timer();

public Scheduler() {
}

public void cancel() {


timer.cancel();
}

public void schedule(SchedulerTask schedulerTask,


ScheduleIterator iterator) {

Date time = iterator.next();


if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.VIRGIN) {
throw new IllegalStateException("Task already
scheduled " + "or cancelled");
}
schedulerTask.state = SchedulerTask.SCHEDULED;
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}

private void reschedule(SchedulerTask schedulerTask,


ScheduleIterator iterator) {

Date time = iterator.next();


if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.CANCELLED) {
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
}

Listing 6 shows the source code for the SchedulerTaskclass:

Listing 6. SchedulerTask

package org.tiling.scheduling;

import java.util.TimerTask;

public abstract class SchedulerTask implements Runnable {

final Object lock = new Object();

int state = VIRGIN;


static final int VIRGIN = 0;
static final int SCHEDULED = 1;
static final int CANCELLED = 2;

TimerTask timerTask;

protected SchedulerTask() {
}

www.ibm.com/developerworks/java/library/j-schedule/index.html 4/9
7/26/12 Scheduling recurring tasks in Java applications

public abstract void run();

public boolean cancel() {


synchronized(lock) {
if (timerTask != null) {
timerTask.cancel();
}
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}

public long scheduledExecutionTime() {


synchronized(lock) {
return timerTask == null ? 0 : timerTask.scheduledExecutionTime();
}
}

Like the egg timer, every instance of Schedulerowns an instance of Timerto provide the underlying scheduling. Instead of the single one-shot timer used to
implement the egg timer, Schedulerstrings together a chain of one-shot timers to execute a SchedulerTaskclass at the times specified by a
ScheduleIterator.

Consider the public schedule()method on Scheduler-- this is the entry point for scheduling because it is the method a client calls. (The only other public
method, cancel(), is described in Canceling tasks.) The time of the first execution of the SchedulerTaskis discovered by calling next()on the
ScheduleIteratorinterface. The scheduling is then kicked off by calling the one-shot schedule()method on the underlying Timerclass for execution at this
time. The TimerTaskobject supplied for one-shot execution is an instance of the nested SchedulerTimerTaskclass, which packages up the task and the
iterator. At the allotted time, the run()method is called on the nested class, which uses the packaged task and iterator references to reschedule the next execution
of the task. The reschedule()method is very similar to the schedule()method, except that it is private and performs a slightly different set of state checks on
SchedulerTask. The rescheduling process repeats indefinitely, constructing a new nested class instance for each scheduled execution, until the task or the
scheduler is cancelled (or the JVM shuts down).

Like its counterpart TimerTask, SchedulerTaskgoes through a series of states during its lifetime. When created, it is in a VIRGINstate, which simply means it
has never been scheduled. Once scheduled, it shifts to a SCHEDULEDstate, then later to a CANCELLEDstate if the task is cancelled by one of the methods described
below. Managing the correct state transitions, such as ensuring that a non- VIRGINtask is not scheduled twice, adds extra complexity to the Schedulerand
SchedulerTaskclasses. Whenever an operation is performed that might change the state of the task, the code must synchronize on the task's lock object.

Canceling tasks

There are three ways to cancel a scheduled task. The first is to call the cancel()method on the SchedulerTask. This is like calling cancel()on a TimerTask:
the task will never run again, although it will run to completion if already running. The return value of the cancel()method is a booleanthat indicates whether
further scheduled tasks might have run had cancel()not been called. More precisely, it returns trueif the task was in a SCHEDULEDstate immediately prior to
calling cancel(). If you try to reschedule a cancelled (or even scheduled) task, Schedulerthrows an IllegalStateException.

The second way to cancel a scheduled task is for ScheduleIteratorto return null. This is simply a shortcut for the first way, as the Schedulerclass calls
cancel()on the SchedulerTaskclass. Canceling a task this way is useful if you want the iterator -- rather than the task -- to control when the scheduling stops.

The third way is to cancel the whole Schedulerby calling its cancel()method. This cancels all the scheduler's tasks and leaves it in a state where no more tasks
may be scheduled on it.

Extending the cron facility

The scheduling framework could be likened to the UNIX cronfacility, except that the specification of scheduling times is controlled imperatively rather than
declaratively. For example, the DailyIteratorclass used in the implementation of AlarmClockhas the same scheduling as a cronjob, specified by a crontab
entry beginning 0 7 * * *. (The fields specify minute, hour, day of month, month, and day of week, respectively.)

However, the scheduling framework has more flexibility than cron. Imagine a HeatingControllerapplication that switches the hot water on in the mornings. I
would like to instruct it to "turn the hot water on at 8:00 AM on weekdays and 9:00 AM on weekends." Using cron, I would need two crontabentries (0 8 *
* 1,2,3,4,5and 0 9 * * 6,7). By using a ScheduleIterator, the solution is more elegant because I can define a single iterator using composition. Listing 7
shows one way to do this:

Listing 7. Using composition to define a single iterator

int[] weekdays = new int[] {


Calendar.MONDAY,
Calendar.TUESDAY,
Calendar.WEDNESDAY,
Calendar.THURSDAY,
Calendar.FRIDAY
};
int[] weekend = new int[] {
Calendar.SATURDAY,
Calendar.SUNDAY
};
www.ibm.com/developerworks/java/library/j-schedule/index.html 5/9
7/26/12 Scheduling recurring tasks in Java applications
ScheduleIterator i = new CompositeIterator(
new ScheduleIterator[] {
new RestrictedDailyIterator(8, 0, 0, weekdays),
new RestrictedDailyIterator(9, 0, 0, weekend)
}
);

A RestrictedDailyIteratorclass is like DailyIterator, except it is restricted to run on particular days of the week; and a CompositeIteratorclass
takes a set of ScheduleIterators and correctly orders the dates into a single schedule. See Resources for the source code to these classes.

There are many other schedules that croncannot produce, but an implementation of ScheduleIteratorcan. For instance, the schedule described by "the last
day of every month" can be implemented using standard Java calendar arithmetic (using the Calendarclass), whereas it is impossible to express this using cron.
Applications don't even have to use the Calendarclass. In the source code for this article (see Resources), I have included an example of a security light controller
that runs to the schedule "turn the lights on 15 minutes before sunset." The implementation uses the Calendrical Calculations Software Package (see Resources) to
compute the time of the sunset locally (given the latitude and longitude).

Real-time guarantees

When writing applications that use scheduling, it is important to understand what the framework promises in terms of timeliness. Will my tasks be executed early or
late? If so, what's the maximum margin of error? Unfortunately, there are no simple answers to these questions. However, in practice the behavior is good enough
for a large class of applications. The discussion below assumes that the system clock is correct (see Resources for information on the Network Time Protocol).

Because Schedulerdelegates its scheduling to the Timerclass, the real-time guarantees that Schedulercan make are identical to those of Timer. Timer
schedules tasks using the Object.wait(long)method. The current thread is made to wait until it is woken up, which can happen for one of these reasons:

1. The notify()or notifyAll()method is called on the object by another thread.


2. The thread is interrupted by another thread.
3. The thread is woken up in the absence of a notify (known as a spurious wakeup, described in Item 50 of Joshua Bloch's Effective Java Programming
Language Guide -- see Resources).
4. The specified amount of time has elapsed.

The first possibility cannot occur for the Timerclass because the object that wait()is called on is private. Even so, the implementation of Timersafeguards
against the first three causes of early wakeup, thus ensuring that the thread wakes up after the time has elapsed. Now, the documentation comment for
Object.wait(long)states it may wake up after the time has elapsed "more or less", so it is possible that the thread wakes up early. In this case, Timerissues
another wait()for (scheduledExecutionTime - System.currentTimeMillis())milliseconds, thereby guaranteeing that tasks can never be executed
early.

Can tasks be executed late? Yes. There are two main causes of late execution: thread scheduling and garbage collection.

The Java language specification is purposefully vague on thread scheduling. This is because the Java platform is general purpose and targets a wide range of
hardware and associated operating systems. While most JVM implementations have a thread scheduler that is fair, it is by no means guaranteed -- certainly
implementations have different strategies for allocating processor time to threads. Therefore, when a Timerthread wakes up after its allotted time, the time at which
it actually executes its task depends on the JVM's thread scheduling policy, as well as how many other threads are contending for processor time. Therefore, to
mitigate late task execution, you should minimize the number of runnable threads in your application. It is worth considering running schedulers in a separate JVM to
achieve this.

The time that the JVM spends performing garbage collection (GC) can be significant for large applications that create lots of objects. By default, when GC occurs
the whole application must wait for it to finish, which may take several seconds or more. (The command line option -verbose:gcfor the javaapplication
launcher will cause each GC event to be reported to the console.) To minimize pauses due to GC, which may hinder prompt task execution, you should minimize
the number of objects your application creates. Again, this is helped by running your scheduling code in a separate JVM. Also, there are a number of tuning options
that you can try to minimize GC pauses. For instance, incremental GC attempts to spread the cost of the major collections over several minor collections. The
trade-off is that this reduces the efficiency of GC, but this might be an acceptable price for timelier scheduling. (See Resources for more GC tuning hints.)

When was I scheduled?

To determine whether tasks are being run in a timely manner, it helps if the tasks themselves monitor and record any instances of late execution. SchedulerTask,
like TimerTask, has a scheduledExecutionTime()method that returns the time that the most recent execution of this task was scheduled to occur. Evaluating
the expression System.currentTimeMillis() - scheduledExecutionTime()at the beginning of the task's run()method lets you determine how late the
task was executed, in milliseconds. This value could be logged to produce statistics on the distribution of late execution. The value might also be used to decide
what action the task should take -- for example, if the task is too late, it might do nothing. If, after following the guidelines above, your application requires stricter
guarantees of timeliness, consider looking at the Real-time Specification for Java (see Resources for more information).

Conclusion

In this article, I have introduced a simple enhancement to the Java timer framework that permits very flexible scheduling strategies. The new framework is
essentially a generalisation of cron-- in fact, it would be valuable to implement cronas a ScheduleIteratorinterface to provide a pure Java cron
replacement. While not offering strict real-time guarantees, the framework is applicable to a host of general purpose Java applications that need to schedule tasks
on a regular basis.

Download

www.ibm.com/developerworks/java/library/j-schedule/index.html 6/9
7/26/12 Scheduling recurring tasks in Java applications
Description Name Size Download method
Sample code for article j-schedule.zip 225KB HTTP

Information about download methods

Resources

"Tuning Garbage Collection with the 1.3.1 Java Virtual Machine" is a very useful article from Sun with hints on how to minimize your GC pauses.

For even more information on GC from developerWorks, see the following articles:
"Java theory and practice: A brief history of garbage collection" (October 2003)
"Mash that trash" (June 2003)
"Fine-tuning Java garbage collection performance" (January 2003)
"Sensible sanitation, Part 1" (August 2002)
"Sensible sanitation, Part 2" (August 2002)
"Sensible sanitation, Part 3" (September 2002)

In "Java theory and practice: Concurrency made simple (sort of)" (developerWorks, November 2002) Brian Goetz discusses Doug Lea's
util.concurrentlibrary, a treasure trove of concurrency utility classes.

Also by Brian Goetz, "Threading lightly, Part 2: Reducing contention" (developerWorks, September 2001) examines thread contention and how to reduce
it.

Here's the documentation for Timer and TimerTask in the Java SDK 1.4.

Jcrontab is another scheduler written in the Java language, with the emphasis on replacing cron.

The Network Time Protocol (NTP) is a protocol for synchronizing computer clocks.

The Real-time Specification for Java is an extension to the Java platform that provides real-time guarantees.

Effective Java Programming Language Guide by Joshua Bloch (Addison-Wesley, 2001) contains excellent advice (for instance, Item 51: Don't depend
on the thread scheduler).

For everything you want to know about the world's calendars and the algorithms to work with them, see Calendrical Calculations by Nachum Dershowitz
and Edward M. Reingold (Cambridge University Press, 1997).

Chapter 17, Threads and Locks, of The Java Language Specification, Second Edition by James Gosling, Bill Joy, Guy L. Steele Jr., and Gilad Bracha
(Addison-Wesley, 2000) specifies the behavior of the thread scheduler.

Concurrent Programming in Java: Design Principles and Patterns by Doug Lea (Addison-Wesley, 1999) is a great book that delves into all aspects of
concurrency in the Java platform.

You'll find hundreds of articles about every aspect of Java programming in the developerWorks Java technology zone.

About the author

Tom White is Lead Java Developer at Kizoom, a leading UK software company in the delivery of personalised travel information to mobile devices. Clients include
the UK's national train operator, the London public transport system, and UK national bus companies. Since its founding in 1999, Kizoom has used all the
disciplines from Extreme Programming. Tom has been writing Java programs full time since 1996, using most of the standard and enterprise Java APIs, from client
Swing GUIs and graphics to back-end messaging systems. He has a first class honours degree in mathematics from Cambridge University. When not programming,
Tom enjoys making his young daughter laugh and watching 1930s Hollywood films. Contact Tom at tom-at-tiling.org.

Close [x]

developerWorks: Sign in
IBM ID:
Need an IBM ID?
Forgot your IBM ID?

Password:
Forgot your password?
Change your password

Keep me signed in.

By clicking Submit, you agree to the developerWorks terms of use.

www.ibm.com/developerworks/java/library/j-schedule/index.html 7/9
7/26/12 Scheduling recurring tasks in Java applications
Submit Cancel

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but
you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you
post.

All information submitted is secure.

Close [x]

Choose your display name


The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you
post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email
address for privacy reasons.

Display name: (Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

Submit Cancel

All information submitted is secure.

Average rating (205 votes)

1 star 1 star
2 stars 2 stars
3 stars 3 stars
4 stars 4 stars
5 stars 5 stars

Submit

Add comment:

Sign in or register to leave a comment.

Note: HTML elements are not supported within comments.

Notify me when a comment is added1000 characters left

Post

Total comments (6) Show: Most recent comments

How would you extend the HeatingController example to have the controller to stop each day at 3 p.m.?

I have tried by creating a StartHeatingControllerTask and a StopHeatingControllerTask which are the used with RestrictedDailyIterator, but I get :
Exception in thread "Timer-2" java.lang.IllegalStateException: Timer already cancelled.

Posted by tquinn on 15 March 2012

Report abuse

why does it keep printing the current time like "Wake up! It's 05 Mar 2012 17:00:22.171
Wake up! It's 05 Mar 2012 17:00:22.171
Wake up! It's 05 Mar 2012 17:00:22.171
Wake up! It's 05 Mar 2012 17:00:22.171
Wake up! It's 05 Mar 2012 17:00:22.171" before printing the time set for it to be printing? there anyway i could just make it print just the time set for it to be

www.ibm.com/developerworks/java/library/j-schedule/index.html 8/9
7/26/12 Scheduling recurring tasks in Java applications
printed? Thank you in advance..

Posted by uchedim on 05 March 2012

Report abuse

How to apply it to Web application?

Posted by guobilly on 05 September 2011

Report abuse

Nice post. One question I had is around how to have such an application always in running mode. I mean without hooking up the application with batch scheduler
systems like Ctrl-M or CA-7.
Are there ways to register a java batch application like this on Unix Cron or Windows Task Scheduler.

Posted by SushantP on 01 July 2011

Report abuse

Very Interesting. I cant put my finger on it, what design pattern is this :
schedulerTask.timerTask = new SchedulerTimerTask(schedulerTask, iterator);

Its wicked as : you shcedule a wrapper task which has an implementation of TimerTask, which executes the run() of the wrapper task!. - leave alone the beauty
that it accomplishes to reschedule it in the most elegant way.

Another thing : does it need to reassign a new SchedulerTimerTask in the reschedule() mehod?

Posted by TechnoMaverik on 09 June 2011

Report abuse

Print this page Share this page Follow developerWorks

About Feeds and apps Report abuse Faculty


Help Newsletters Terms of use Students

Contact us IBM privacy Business Partners


Submit content IBM accessibility

www.ibm.com/developerworks/java/library/j-schedule/index.html 9/9

You might also like