Scheduling Threads


Some candidates prefer to periodically clear database record locks from the locking mechanism. This approach is valid and easily justified. However, the evaluator will not be impressed if you build a cron (scheduled Unix process) job manager with repetitive time checks using the Date class. Using the thread scheduler in J2SE 1.4 is a much better way to achieve the same goal. Although some candidates might want to give users timed messages in the GUI, the most likely use of the scheduled thread functionality is to periodically scrub database locks.

So far, you have seen how to run multiple threads and how easy it is to put a thread to sleep for a specific amount of time. Developers have been using this method for a long time, and it works well. However, sometimes you need to schedule a thread in a more declarative manner.

What you need is an object that enables you to pass another object to it and specify at what time it should be used. The two parameters of interest are object and time . The object must have a way to start or be started. To do this, extend the abstract TimerTask class, which has the run method, just as the Thread class does. In this object that extends TimerTask , you override the abstract run method. Now the scheduler can invoke the run method when it is scheduled to do so. The second part the scheduler needs is the time, which you can define in three ways: tell the scheduler when to invoke the abstract run method by absolute time, delay the invocation from moment of instantiation by a certain amount of time, and repeat the invocation by time interval. The following list describes different methods of scheduling tasks in the java.util.Timer class:

  • schedule(TimerTask task, Date time) ” Carries out a task at the absolute time.

  • schedule(TimerTask task, Date firstTime, long period) ” Carries out a task at the absolute time and repeats it. Each repetition takes place after a delay defined by period .

  • schedule(TimerTask task, long delay) ” Carries out a task after a delay specified by period .

  • schedule(TimerTask task, long delay, long period) ” Carries out a task after a delay and repeats it. Each repetition takes place after another delay defined by delay .

  • scheduleAtFixedRate(TimerTask task, Date firstTime, long period) ” Carries out a task at the absolute time and repeats it. Each repetition takes place after a delay defined by period .

  • scheduleAtFixedRate(TimerTask task, long delay, long period) ” Carries out a task after a delay and repeats it. Each repetition takes place after another delay defined by period .

As you can see, there are many ways to schedule tasks, a welcome improvement to J2SE.

To see scheduling tasks in action, take a look at Listing 10.4, a second variation of Listing 10.1. This time the Timer class is used. This class takes the manual sleep call out of the code and encapsulates the responsibility for putting a thread to sleep inside a dedicated object.

Listing 10.4 A Multithreaded Application Using Timer
 import java.util.Timer; import java.util.TimerTask; public class MultiThreadScheduled {     public static void main( String [] args )     {         Timer timer = new Timer();         //determine number of new threads         int numberOfThreads = 10;         if (args.length == 1)         {             numberOfThreads = Integer.parseInt(args[0]);         }         System.out.println( "Main Start" );         for(int i = 0; i < numberOfThreads; i++)         {             // create sleep duration in milliseconds = 0-10 seconds             int milliseconds = ( int ) ( Math.random() * (10000 + 1));             // create a new thread             // add it to the scheduler             String threadName = "Thread number " + i;             System.out.println( threadName );             //new MultiThreadScheduled("Thread number " + i, milliseconds);             timer.schedule(new NewThreadScheduled(threadName, milliseconds,                                               timer, false), milliseconds);         }         timer.schedule(new NewThreadScheduled("last thread", 11000,                                                       timer, true), 11000);         System.out.println( "Main Done" );     } } // a new thread class class NewThreadScheduled extends TimerTask {     String threadName = "";     boolean cancelTimer = false;     Timer timer;     // give thread a name     public NewThreadScheduled( String threadName, int milliseconds,                                        Timer timer, boolean cancelTimer)     {        this.threadName = threadName;        this.timer = timer;        this.cancelTimer = cancelTimer;        System.out.println( "created " + threadName );     }     // override the run method in Thread     public void run()     {           // tell system thread is awake           String status = threadName + " is getting up from napping.";           System.out.println( status );           if(cancelTimer) timer.cancel(); //kill timer thread     } } /* results vary between executions: Main Start Thread number 0 created Thread number 0 Thread number 1 created Thread number 1 Thread number 2 created Thread number 2 Thread number 3 created Thread number 3 Thread number 4 created Thread number 4 Thread number 5 created Thread number 5 Thread number 6 created Thread number 6 Thread number 7 created Thread number 7 Thread number 8 created Thread number 8 Thread number 9 created Thread number 9 created last thread Main Done Thread number 9 is getting up from napping. Thread number 7 is getting up from napping. Thread number 4 is getting up from napping. Thread number 5 is getting up from napping. Thread number 6 is getting up from napping. Thread number 0 is getting up from napping. Thread number 1 is getting up from napping. Thread number 8 is getting up from napping. Thread number 2 is getting up from napping. Thread number 3 is getting up from napping. last thread is getting up from napping. */ 

Both listings 10.1 and 10.4 put a given thread to sleep for a random amount of time. That way, the threads wake up randomly. However, there is a fundamental difference between Listing 10.1 and Listing 10.4 where Listing 10.1 creates the threads randomly , but Listing 10.4 creates them in sequence. Listing 10.4 also demonstrates much better control over creating and running threads.

The Timer class is a smart way to schedule work in an application. In order to use it you create an object that extends TimerTask . This object is passed to a Timer for scheduling specific method calls. The idea is to encapsulate work into an object. This gets away from method-specific tasking and keeps the management of work at the object level. It is the same philosophy as hiding implementation or details of the called method from the calling method. For example, if you wanted to schedule a single method, you could simply create a class that extends the TimerTask class. In the run method, you create an instance of the target object and call that method. Listing 10.5 shows you how.

Listing 10.5 Scheduling Specific Method Calls Using Timer
 import java.util.Timer; import java.util.TimerTask; public class ScheduleSingleTask {     public static void main(String args[])     {         int milliseconds = 2500;         Timer timer = new Timer();         System.out.println("SingleTask() has been scheduled.");         timer.schedule(new SingleTask(timer), milliseconds);     } } class SingleTask extends TimerTask {     Timer timer;     public SingleTask(Timer timer)     {         this.timer = timer;     }     public void run()     {         myMethod();         NewObject object = new NewObject();         object.nextMethod();         //kill timer thread         timer.cancel();     }     public void myMethod()     {         System.out.println("SingleTask.myMethod() has executed.");     } } class NewObject {     public void nextMethod()     {         System.out.println("NewObject.nextMethod() has executed.");     } } /* results: SingleTask() has been scheduled. SingleTask.myMethod() has executed. NewObject.nextMethod() has executed. */ 

Scheduling specific method calls by using the Timer and TimerTask classes is a powerful new feature of J2SE 1.4. Developers used to write complex multithreaded modules to accomplish the same goal, but now you have an easy way to handle scheduling method calls. You can use it in your solution to great effect. For example, suppose you wanted to schedule occasional reminders to users about the current status of their reservations . You could schedule a status message that's displayed to the user every 10 seconds or so, but in a nondescript manner. Placing a message at the bottom of the GUI about the user's last few steps and listing the steps clearly could make the GUI more user friendly.

graphics/tip_icon.gif

What do you do if your class must subclass another class? So far, you have extended Thread to create a separate thread. However, you can also accomplish the same thing, and override the run method, by implementing the Runnable interface.




JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 187

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net