Implementing

   

Implementing Runnable

The second way to cause classes to behave as threads is to have those classes implement the java.lang.Runnable interface. A second method is available because extending the Thread class will not work in all cases. This is because Java does not allow for a class to be a subclass of more than one direct parent class. Other languages such as C++ do allow this, but Java does not. For example, the SimpleThread class shown previously could not extend Thread and Date classes simultaneously .

If you need to create a new class that acts as a thread and this new class already extends a different class, the alternative is to have the new class implement the Java Runnable interface instead. The Runnable interface defines a single interface operation, the run method. Therefore, if you have a class implement the Runnable interface, it must implement the run method. All the work the class will do when running as a thread goes in the run method. Listing 11.2 shows the alternative approach.

Listing 11.2 Source Code for SimpleThread2.java
 public class SimpleThread2 extends java.util.Date implements Runnable {   private String threadName = null;   // Default Constructor   public SimpleThread2(String name)   {     super();     threadName = name;   }   // Private accessor for the instance variable   private String getThreadName()   {     return this.threadName;   }   // Implement the run method required from the Runnable interface   public void run()   {     // Do the thread work here     this.setTime(System.currentTimeMillis());     System.out.println(getThreadName() + ": " + this.toString());   } } 

This class can now be used as a parameter to the Thread constructor. When that thread instance is started, the run method is executed. Listing 11.3 shows the source code for the test class that uses the SimpleThread2 from Listing 11.2. This is a simple run method that prints out a date instance and then quits, but it gives you the necessary idea on how to use the Runnable interface.

Troubleshooting Tip

If you are having trouble with starting a thread, see "Thread Does Not Start," in the "Troubleshooting" section at the end of this chapter.


Listing 11.3 Source Code for SimpleThread2Main.java
 public class SimpleThread2Main {   public static void main(String[] args)   {     // Create an instance of our new class that implements the     // Runnable interface     SimpleThread2 simpleThread = new SimpleThread2("SimpleThread2");     // Create a new instance of a thread using our Runnable class     // as the target and tell it to use "SimpleThread2" as the name     Thread newThread = new Thread(simpleThread, "SimpleThread2");       // Start the thread     newThread.start();   } } 

Here is the output when you run the SimpleThread2Main class from the previous listing:

 C:\jdk1.3se_book\classes>java SimpleThread2Main SimpleThread2: Wed Apr 26 21:27:53 PDT 2000 C:\jdk1.3se_book\classes> 

Notice that the only thing printed out is the text from the println method in the run method as expected. The second parameter to the Thread constructor sets up a name for the thread. This is mainly for display purposes. When using the Runnable interface approach, there isn't an easy way to get access to the thread that it's running within. That's why a private variable was added in the SimpleThread2 class to hold onto the name. When extending the Thread class, the variable is already defined and you can use the getName method to retrieve the name of the Thread.

Note

The Thread class actually already implements the Runnable interface itself. The Runnable interface has only one method: run. Any time you make a class implement Runnable, you need to have a run method in your class. In the run method, you actually do all the work you want to have done by that particular thread.


Listing 11.4 shows another example of a new Thread class. In this example, the first method of extending the Thread class is used rather than the Runnable interface. In fact, the SimpleThread class from before is used to do a little more work.

Listing 11.4 Source Code for SimpleThread.java
 public class SimpleThread extends Thread {   // Default Constructor   public SimpleThread(String threadName)   {     // Set the name of the thread for display purposes     setName(threadName);     System.out.println(threadName + " has been created");   }   // Override the parents run method to get the work done   public void run()   {     // Do the thread work here     System.out.println(getName() + " entered run method");     try     {       System.out.println(getName() + " going to sleep");       // Tell this thread to go to sleep for 3,000 milliseconds       sleep(3000);     }     catch(InterruptedException ex)     {       // Do nothing for now when this exception is raised     }     System.out.println(getName() + "  woke up from sleep");   } } 

Listing 11.5 shows the main class used for testing the SimpleThread.java class.

Listing 11.5 Source Code for TestMain.java
 public class TestMain {   public static final int NUMBER_OF_THREADS = 5;   public static void main(String[] args)   {     SimpleThread[] threads = new SimpleThread[NUMBER_OF_THREADS];     for(int i = 0; i < NUMBER_OF_THREADS; i++)     {       String name = "Thread: " + i;       SimpleThread newThread = new SimpleThread(name);       threads[i] = newThread;     }     for (int i = 0; i < NUMBER_OF_THREADS; i++)     {       threads[i].start();     }   } } 

In this example, the class called SimpleThread has been expanded. It extends the Thread class and overrides the run method that it inherits from the Thread class. In the run method, it prints some basic information to the screen to let you know what's going on. In the constructor of the class, the name for this thread is passed in as a parameter to the constructor and you set the name for this instance.

The name property on a Thread class is used for identification purposes. The name is not required to be unique, but it might get confusing if you are using the names somewhere and you use the same names for different threads. If you don't assign a name to a thread, the VM will set one for you automatically. You only need to give it a name if you will be interested in that name later.

The other thing to notice in this simple example is the sleep method being called in the run method. The sleep method causes the thread to temporarily cease execution for the speci fied amount of milliseconds set in the parameter. Notice that the java.lang.InterruptedException must be caught even if you aren't interested in doing anything with that exception. The InterruptedException will be thrown if another thread interrupts this one. It will not be called when the thread comes out of the sleep.

The TestMain class is used to test the new SimpleThread class. This class has a public static final int variable called NUMBER_OF_THREADS that you can change to see the different behavior as you vary the number of threads being created. The TestMain class uses an array to instantiate the number of threads that the NUMBER_OF_THREADS variables declare and after all the threads are instantiated and stored in the array, it goes through the array and tells each thread to start. It was done this way so that you could get each thread to enter the run method as fast as possible for the purpose of this example. An instance of the SimpleThread class could have been instantiated and at the same time its start method called, but this way there is less lag time between the instantiation and the start of the run method being called.

If you run the previous example from the command line, the output looks something like this:

The following text shows the output when TestMain.java from Listing 11.5 is executed:

 C:\jdk1.3se_book\classes>java TestMain Thread-0 entered run method Thread-0 going to sleep Thread-1 entered run method Thread-2 entered run method Thread-3 entered run method Thread-4 entered run method Thread-1 going to sleep Thread-2 going to sleep Thread-3 going to sleep Thread-4 going to sleep Thread-0  woke up from sleep Thread-1  woke up from sleep Thread-2  woke up from sleep Thread-4  woke up from sleep Thread-3  woke up from sleep C:\jdk1.3se_book\classes> 

Note

If your output looks similar to this, but not in the same order, don't worry. This is a good example of not being guaranteed which thread will be doing what when. Play around with changing the number of threads created by adjusting the NUMBER_OF_THREADS constant in the TestMain class. Also, change the sleep time and see how the output varies. You should also notice that the first Thread is number 0. This is because the Threads are being stored in an array and the first position of an array is 0.


Troubleshooting Tip

If you are having trouble with seeing all of your threads starting, check "One Off Error," in the "Troubleshooting" section at the end of this chapter.


   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

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