Summary

Chapter 5 - Gracefully Stopping Threads

Java Thread Programming
Paul Hyde
  Copyright 1999 Sams Publishing

Stopping a Thread
A thread is considered to be alive from just after the start() method of Thread is invoked until it dies. A thread may die by returning from run() which is the case in the examples so far. A thread may also die when the stop() method of Thread is invoked. Like suspend() and resume() , stop() has been deprecated as of JDK 1.2.
Using the Deprecated Method stop()
At times, one of the additional threads spawned in a multithreaded program is no longer needed, but it continues to execute statementsperhaps in an infinite loop. The Thread API includes a stop() method to abruptly terminate a threads execution:
public final void stop()
When this method is invoked on a thread, the thread immediately throws a java.lang.ThreadDeath error (a subclass of java.lang.Error , which itself is a subclass of java.lang.Throwable ). This exception propagates up the method call stack, executing any finally clauses present and releasing any locks that are currently held. Ultimately, this exception causes run() to abruptly return, and the thread dies.
The class DeprecatedStop , in Listing 5.9, shows a very simple example of how to use stop() .
Listing 5.9  DeprecatedStop.javaAn Example Using the Deprecated stop() Method
1: public class DeprecatedStop extends Object implements Runnable {
2:
3:     public void run() {
4:         int count = 0;
5:
6:         while ( true ) {
7:             System.out.println(Running ... count= + count);
8:             count++;
9:
10:             try {
11:                 Thread.sleep(300);
12:             } catch (InterruptedException x) {
13:                 // ignore
14:             }
15:         }
16:     }
17:
18:
19:     public static void main(String[] args) {
20:         DeprecatedStop ds = new DeprecatedStop();
21:         Thread t = new Thread(ds);
22:         t.start();
23:
24:         try {
25:             Thread.sleep(2000);
26:         } catch (InterruptedException x) {
27:             // ignore
28:         }
29:
30:         // Abruptly stop the other thread in its tracks!
31:         t.stop();
32:     }
33: }
The main thread creates a new DeprecatedStop object (line 20) and a new Thread object (line 21) and starts the thread running (line 22). It then sleeps for two seconds while the new thread runs.
The new thread runs an infinite while loop (lines 615). In this loop, it prints a message with the latest count (line 7), increments count , and then sleeps for 300 milliseconds . This is done until the thread is stopped .
Back in the main() method, the main thread wakes up after its 2-second nap and abruptly stops the new thread (line 31).
When run, it produces the following output (your output should match):
Running ... count=0
Running ... count=1
Running ... count=2
Running ... count=3
Running ... count=4
Running ... count=5
Running ... count=6
The stop() method is deprecated as of JDK 1.2 because it can lead to corrupted data in objects. One problem is that when a thread is stopped abruptly, there is little opportunity to perform any cleanup work. Another problem is that when stop() is invoked on a thread, the thread releases all the locks it is currently holding. The locks are definitely being held for a good reasonprobably to keep other threads from accessing data elements that are not yet in a consistent state. This sudden release of the locks may leave some data in some objects in an inconsistent state with no warning about the possible corruption. In many cases, there are other ways to have a thread return from run() in an orderly manner that leaves all objects in a consistent state.
  Tip Although stop() is not deprecated in JDK 1.0 and 1.1, it should not be used for the same good reasons that it is deprecated in JDK 1.2. Alternative techniques to very closely simulate and safely replace the functionality of stop() are presented next .
An Alternative to stop()
As an alternative to directly stopping a thread, a boolean indicator variable can be used to determine whether the thread should continue processing. In conjunction with this, the interrupt() method can be used to signal the thread that it should take a different course of action. Earlier in this chapter, the class PiInterrupt (refer to Listing 5.5 ) uses interrupt() to signal the new thread that it should stop refining its calculation and bail out.
The class AlternateStop , in Listing 5.10, shows how interrupt() and a boolean indicator can be used together to get a thread to safely stop.
Listing 5.10  AlternateStop.javaUsing interrupt() and a boolean Flag to Safely Stop a Thread
1: public class AlternateStop extends Object implements Runnable {
2:     private volatile boolean stopRequested;
3:     private Thread runThread;
4:
5:     public void run() {
6:         runThread = Thread.currentThread();
7:         stopRequested = false;
8:
9:         int count = 0;
10:
11:         while ( !stopRequested ) {
12:             System.out.println(Running ... count= + count);
13:             count++;
14:
15:             try {
16:                 Thread.sleep(300);
17:             } catch (InterruptedException x) {
18:                 Thread.currentThread().interrupt(); // reassert
19:             }
20:         }
21:     }
22:
23:     public void stopRequest() {
24:         stopRequested = true;
25:
26:         if (runThread != null) {
27:             runThread.interrupt();
28:         }
29:     }
30:
31:     public static void main(String[] args) {
32:         AlternateStop as = new AlternateStop();
33:         Thread t = new Thread(as);
34:         t.start();
35:
36:         try {
37:             Thread.sleep(2000);
38:         } catch (InterruptedException x) {
39:             // ignore
40:         }
41:
42:         as.stopRequest();
43:     }
44: }
In main() , a new thread is spawned (lines 3234) to run inside an AlternateStop instance. The main thread then sleeps for two seconds to let the new thread run (lines 3640).
The volatile member variable stopRequested (line 2) is used as the flag to indicate whether the thread should continue to run. The member variable runThread (line 3) is used to keep a reference to the thread that is currently running inside run() .
When run() is invoked, the current thread is stored in runThread (line 6) for later use, and stopRequested is set to false . The while loop (lines 1120) continues until stopRequested is true . Inside the while loop, any time a InterruptedException might be thrown, it should be caught (line 17) and reasserted (line 18). The interrupt flag should be reasserted in case any other statements yet to be executed in the loop have to be interrupted (in this example, it doesnt apply, but its a good habit to get into). If there were more interruptible statements like sleep() or wait() , they would not throw an InterruptedException unless the interrupt had been reasserted. You do want them to throw an InterruptedException right away because the thread has been signaled to clean up and die.
Back in the main thread, after the two-second nap, the stopRequest() method of AlternateStop is invoked (line 42) to put in a request that the new thread die as soon as possible. When stopRequest() is invoked, stopRequested is set to true (line 24), and the thread that is running inside run() is interrupted (line 27).
When run, it produces the following output (your output should match):
Running ... count=0
Running ... count=1
Running ... count=2
Running ... count=3
Running ... count=4
Running ... count=5
Running ... count=6

Toc


Java Thread Programming
Java Thread Programming
ISBN: 0672315858
EAN: 2147483647
Year: 2005
Pages: 149
Authors: Paul Hyde

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