Recipe 24.1 Running Code in a Different Thread


Problem

You need to write a threaded application.

Solution

Write code that implements Runnable; instantiate and start it.

Discussion

There are several ways to implement threading, and they all require you to implement the Runnable interface. Runnable has only one method, whose signature is:

public void run( );

You must provide an implementation of the run( ) method. When this method returns, the thread is used up and can never be restarted or reused. Note that there is nothing special in the compiled class file about this method; it's an ordinary method and you could call it yourself. But then what? There wouldn't be the special magic that launches it as an independent flow of control, so it wouldn't run concurrently with your main program or flow of control. For this, you need to invoke the magic of thread creation.

One way to do this is simply to subclass from java.lang.Thread (which also implements this interface; you do not need to declare redundantly that you implement it). This approach is shown in Example 24-1. Class ThreadsDemo1 simply prints a series of "Hello from X" and "Hello from Y" messages; the order in which they appear is indeterminate since there is nothing in either Java or the program to determine the order of things.

Example 24-1. ThreadsDemo1.java
/**   * Threaded demo application, as a Threads subclass.  */ public class ThreadsDemo1 extends Thread {     String mesg;     int count;     /** Run does the work: print a message, "count" number of times */      public void run( ) {         while (count-- > 0) {             println(mesg);             try {                 Thread.sleep(100);    // 100 msec             } catch (InterruptedException e) {                 return;             }         }         println(mesg + " all done.");     }     void println(String s) {         System.out.println(s);     }     /**      * Construct a ThreadsDemo1 object.      * @param m Message to display      * @param n How many times to display it      */     public ThreadsDemo1(String m, int n) {         count = n;         mesg  = m;         setName(m + " runner Thread");     }     /**      * Main program, test driver for ThreadsDemo1 class.      */     public static void main(String[] argv) {         // could say: new ThreadsDemo1("Hello from X", 10).run( );         // could say: new ThreadsDemo1("Hello from Y", 15).run( );         // But then it wouldn't be multi-threaded!         new ThreadsDemo1("Hello from X", 10).start( );         new ThreadsDemo1("Hello from Y", 15).start( );     } }

What if you can't subclass Thread because you're already subclassing another class, such as JApplet? There are two other ways to do it: have a class implement the Runnable interface, or use an inner class to provide the Runnable implementation. Example 24-2 is code that implements Runnable.

Example 24-2. ThreadsDemo2.java
public class ThreadsDemo2 implements Runnable {     String mesg;     Thread t;     int count;     /**      * Construct a ThreadsDemo2 object      *      * @param    String m    Message to display      * @param    int n        How many times to display it      */     public ThreadsDemo2(String m, int n) {         count = n;         mesg  = m;         t = new Thread(this);         t.setName(m + " printer thread");     }

The run method itself does not change, so I've omitted it from this listing. To complete the discussion, Example 24-3 is a version of this class that uses an inner class to provide the run method.

Example 24-3. ThreadsDemo3.java
public class ThreadsDemo3 {     String mesg;     Thread t;     int count;     /**      * Main program, test driver for ThreadsDemo3 class.      */     public static void main(String argv[]) {         new ThreadsDemo3("Hello from X", 10);         new ThreadsDemo3("Hello from Y", 15);     }     /**      * Construct a ThreadsDemo3 object      * @param m message to display      * @param n How many times to display it      */     public ThreadsDemo3(String m, int n) {         count = n;         mesg  = m;         t = new Thread(new Runnable( ) {             public void run( ) {                 while (count-- > 0) {                     System.out.println(mesg);                     try {                         Thread.sleep(100);    // 100 msec                     } catch (InterruptedException e) {                         return;                     }                 }                 System.out.println(mesg + " thread all done.");             }         });         t.start( );     }

Here the run method is part of the anonymous inner class declared in the statement beginning t = new Thread(...). This runs with no interaction with other classes, so it's a good use of an inner class.

To summarize, you can create a Runnable in three ways:

  • Extend Thread as ThreadsDemo1 did. This works best for standalone applications that don't need to extend another class.

  • Implement the Runnable interface. This works for applets that extend JApplet and cannot extend Thread due to single inheritance.

  • Construct a Thread passing an inner class that is a Runnable. This is best for tiny run methods with little outside interaction.

Thread lifecycle methods

I should mention a few other methods briefly, starting with the Thread constructors: Thread( ), Thread("Thread Name"), and Thread(Runnable). The no-argument and name-argument constructors are used only when subclassing. But what's in a name? Well, by default, a thread's name is composed of the class name and a number such as a sequence number or the object's hashcode; on Sun's JDK it uses sequence numbers, such as Thread-0, Thread-1, and so on. These names are not very descriptive when you need to look at them in a debugger, so assigning names like "Clock Ticker Thread" or "Background Save Thread" will make your life easier when (not if) you wind up having to debug your threaded application. Because of this, getName( )/setName(String) methods return or change the thread's name, respectively.

We've seen already that the start( ) method begins the process of assigning CPU time to a thread, resulting in its run( ) method being called. The corresponding stop( ) method is deprecated; see Recipe 24.3, where I also discuss interrupt( ) , which interrupts whatever the thread is doing. The method boolean isAlive( ) returns true if the thread has neither finished nor been terminated by a call to its stop( ) method. Also deprecated are suspend( )/resume( ) , which pause and continue a thread; they are prone to corruption and deadlocking, so they should not be used. If you've created multiple threads, you can join( ) a thread to wait for it to finish; see Recipe 24.4.

The methods int getPriority( )/void setPriority(int) show and set the priority of a thread; higher priority threads get first chance at the CPU. Finally, wait( )/notify( )/notifyAll( ) allow you to implement classical semaphore handling for such paradigms as producer/consumer relationships. See the Javadoc page for the Thread class for information on a few other methods.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

Similar book on Amazon

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