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 two ways to implement threading, and both 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 ThreadsDemo simply prints a series of Xs and Ys; 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    String m    Message to display
     * @param    int 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 ThreadDemo 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 ThreadDemo object
     *
     * @param    String m    Message to display
     * @param    int 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, there are three ways of having a Runnable:

  • 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 life cycle methods

There are other methods that I should mention briefly, starting with the Thread constructors: Thread( ), Thread("Thread Name"), Thread(Runnable), etc. 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 JDK 1.3 it uses sequence numbers, such as Thread-0, Thread-1, and so on. These are not very interesting 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, there are also getName( )/setName(String) methods, which 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 Section 24.4, 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 Section 24.5.

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. There are a few other methods: see the Javadoc page for the Thread class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.218.45