Using the Timer and TimerTask Classes

In version 1.3, support for timers was added to the java.util package. The Timer [1] class in that package schedules instances of a class called TimerTask. [2] Here's an example of using a timer to perform a task after a delay, Reminder.java. [3]

[1] http://java.sun.com/j2se/1.3/docs/api/java/util/Timer.html

[2] http://java.sun.com/j2se/1.3/docs/api/java/util/TimerTask.html

[3] Reminder.java is included on the CD and is available online. See Code Samples (page 310).

import java.util.Timer; import java.util.TimerTask; /** * Simple demo that uses java.util.Timer to schedule a task to execute * once 5 seconds have passed. */ public class Reminder { Timer timer; public Reminder(int seconds) { timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); } class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); timer.cancel(); //Terminate the timer thread } } public static void main(String args[]) { new Reminder(5); System.out.println("Task scheduled."); } }

When you run the example, you first see this:

Task scheduled.

Five seconds later, you see this:

Time's up!

This simple program illustrates the basic parts of implementing and scheduling a task to be executed by a timer thread.

//Get the Date corresponding to 11:01:00 pm today. Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, 0); Date time = calendar.getTime(); timer = new Timer(); timer.schedule(new RemindTask(), time);

Stopping Timer Threads

By default, a program keeps running as long as its timer threads are running. You can terminate a timer thread in four ways.

The Reminder example uses the first scheme, invoking the cancel method from the timer task's run method. Making the timer thread a daemon wouldn't work, because the program needs to keep running until the timer's task executes.

Sometimes, timer threads aren't the only threads that can prevent a program from exiting when expected. For example, if you use the AWT at alleven if only to make beepsthe AWT automatically creates a nondaemon thread that keeps the program alive. The following modification of Reminder adds beeping, which requires us to also add a call to the System.exit method to make the program exit. Significant changes are in boldface. You can find the source code in ReminderBeep.java. [1]

[1] ReminderBeep.java is included on the CD and is available online. See Code Samples (page 310).

... public class ReminderBeep { ... public ReminderBeep(int seconds) { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); } class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); toolkit.beep(); //timer.cancel(); //Not necessary because we call System.exit System.exit(0); //Stops the AWT thread (and everything else) } } ... }

Performing a Task Repeatedly

Here's an example of using a timer to perform a task once per second.

public class AnnoyingBeep { Toolkit toolkit; Timer timer; public AnnoyingBeep() { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), 0, //initial delay 1*1000); //subsequent rate } class RemindTask extends TimerTask { int numWarningBeeps = 3; public void run() { if (numWarningBeeps > 0) { toolkit.beep(); System.out.println("Beep!"); numWarningBeeps--; } else { toolkit.beep(); System.out.println("Time's up!"); //timer.cancel(); //Not necessary //because we call System.exit System.exit(0); //Stops the AWT thread //(and everything else) } } } ... }

You can find the entire program in AnnoyingBeep.java. [1] When you execute it, you see the following output (our comments about timing are shown in italics):

[1] AnnoyingBeep.java is included on the CD and is available online. See Code Samples (page 310).

Task scheduled. Beep! Beep! //one second after the first beep Beep! //one second after the second beep Time's up! //one second after the third beep

The AnnoyingBeep program uses a three-argument version of the schedule method to specify that its task should execute once a second, beginning immediately. Here are all the Timer methods you can use to schedule repeated executions of tasks:

When scheduling a task for repeated execution, you should use one of the schedule methods when smoothness is important and a scheduleAtFixedRate method when time synchronization is more important. For example, the AnnoyingBeep program uses the schedule method, which means that the annoying beeps will all be at least 1 second apart. If one beep is late for any reason, all subsequent beeps will be delayed. If we decide that the AnnoyingBeep program should exit exactly 3 seconds after the first beepeven if it means that two beeps might occur close together if a beep is delayed for any reasonwe should use the scheduleAtFixedRate method instead.

More Information about Timers

The timer tasks we've shown have been very simple. They do almost nothing and refer only to data that either can be safely accessed from multiple threads or is private to the timer task. As long as your timer task uses only API designed to be thread-safesuch as the methods in the Timer classimplementing timers is relatively straightforward. However, if your timer implementation depends on shared resources, such as data used by other places in your program, you need to be careful. You can find out more later in this chapter in the section Synchronizing Threads (page 291).

For further information about timers, see

Категории