The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Trail: Essential Java Classes
Lesson: Threads: Doing Two or More Tasks At Once

## Using the Timer and TimerTask Classes

> In version 1.3, support for timers was added to the `java.util` package. The `Timer` class in that package schedules instances of a class called `TimerTask`.

> > Note: If you’re writing a program with a graphical user interface (GUI), you might want to use the `javax.swing.Timer` class (added in version 1.2) instead of `java.util.Timer`. Another utility class, `SwingWorker`, helps you with another common job: performing a task in a background thread, optionally updating the GUI when the task completes. You can find information about both classes in How to Use Threads, a section in the trail Creating a GUI with JFC/Swing.

> Here's an example, ``Reminder.java``, of using a timer to perform a task after a delay.

> >     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[]) {
> >             System.out.println("About to schedule task.");
> >             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.

> - Implement a custom subclass of `TimerTask`. The `run` method contains the code that performs the task. In this example, the subclass is named `RemindTask`.
> - Create a thread by instantiating the `Timer` class.
> - Instantiate the timer task object (`new RemindTask()`).
> - Schedule the timer task for execution. This example uses the `schedule` method, with the timer task as the first argument and the delay in milliseconds (`5000`) as the second argument. Another way of scheduling a task is to specify the time when the task should execute. For example, the following code schedules a task for execution at 11:01 p.m.:

>   >     //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.
> - Invoke `cancel` on the timer. You can do this from anywhere in the program, such as from a timer task’s `run` method.
> - Make the timer’s thread a “daemon” by creating the timer like this: `new Timer(true)`. If the only threads left in the program are daemon threads, the program exits.
> - After all the timer’s scheduled tasks have finished executing, remove all references to the `Timer` object. Eventually, the timer’s thread will terminate.
> - Invoke the `System.exit` method, which makes the entire program (and all its threads) exit.
> 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 all—even if only to make beeps—the 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``.

> >     ...
> >     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``. When you execute it, you see the following output (our comments about timing are shown in italics):

> >     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:
> - `schedule(TimerTask task, long delay, long period)`
> - `schedule(TimerTask task, Date time, long period)`
> - `scheduleAtFixedRate(TimerTask task, long delay, long period)`
> - `scheduleAtFixedRate(TimerTask task, Date firstTime, long period)`

> 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 beep—even if it means that two beeps might occur close together if a beep is delayed for any reason—we 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-safe—such as the methods in the `Timer` class—implementing 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.

> For further information about timers, see

> - The API documentation for `Timer` and `TimerTask`
> - Using Timers in Swing Applications, an article in the online magazine The Swing Connection.
> - The May 30, 2000, edition of the Java Developer Connection "Tech Tips".
> - For information about GUI-specific timer facilities, How to Use Threads, a section in the trail Creating a GUI with JFC/Swing.

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Copyright 1995-2001 Sun Microsystems, Inc. All rights reserved.