...
Wiki Markup |
---|
However, the {{Thread.stop()}} method causes the thread to stop what it is doing and throw a {{ThreadDeath}} exception,. andAll releaseacquired all locks thatare itsubsequently has acquiredreleased \[[API 06|AA. Java References#API 06]\]. If the thread is in the process of adding a new integer to the vector when it is stopped, the vector may become accessible while it is in an inconsistent state. For example, {{Vector.size()}} may bereturn two while the vector contains three elements (the element count is incremented after adding the element). |
...
Code Block | ||
---|---|---|
| ||
public class Container implements Runnable { private final Vector<Integer> vector = new Vector<Integer>(); public Vector<Integer> getVector() { return vector; } public synchronized void run() { Random number = new Random(123L); int i = 10; while (!Thread.interrupted() && i > 0) { vector.add(number.nextInt(100)); i--; } } public static void main(String[] args) throws InterruptedException { Container c = new Container(); Thread thread = new Thread(c); thread.start(); Thread.sleep(5000); thread.interrupt(); } } |
...
This method interrupts the current thread, however, it only stops the thread because the thread logic code polls the interrupted flag using the method {{Thread.interrupted()
}}, and shuts down when it is interrupted. No guarantees are provided by the JVM on when the interruption will be detected by blocking methods such as {{is interrupted.
Upon receiving the interruption, the interrupted status of the thread is cleared and an InterruptedException
is thrown. No guarantees are provided by the JVM on when the interruption will be detected by blocking methods such as Thread.sleep()
}} and {{Object.wait()
}} \[[Goetz 06|AA. Java References#Goetz 06]\]. Upon receiving the interruption, the interrupted status of the thread is cleared and an {{InterruptedException}} is thrown. Note that a thread should not be interrupted unless its interruption policy is known in advance. Failure to follow this advice can result in the corruption of mutable shared . A thread may use interruption for performing tasks other than cancellation and shutdown. Consequently, a thread should not be interrupted unless its interruption policy is known in advance. Failure to follow this advice can result in the corruption of mutable shared state.
Compliant Solution (RuntimePermission stopThread
)
...
This noncompliant code example uses a volatile done
flag to indicate when the thread should shut down flag to indicate that it is safe to shutdown the thread, as suggested above. However, this does not help in terminating the thread because it is blocked on some network IO as a consequence of using the readLine()
method.
Code Block | ||
---|---|---|
| ||
class SocketReader implements Runnable {
private final Socket socket;
private final BufferedReader in;
private volatile boolean done = false;
private final Object lock = new Object();
private boolean isRunning = false; // Reduces the need to synchronize time consuming operations
public static class MultipleUseException extends RuntimeException {};
public SocketReader() throws IOException {
this.socket = new Socket("somehost", 25);
this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
}
// Only one thread can use the socket at a particular time
public void run() {
try {
synchronized (lock) {
if (isRunning) {
throw new MultipleUseException();
}
isRunning = true;
}
execute();
} catch (IOException ie) {
// Forward to handler
}
}
public void execute() throws IOException {
String string;
while (!done && (string = in.readLine()) != null) {
// Blocks until end of stream (null)
}
}
public void shutdown() {
done = true;
}
public static void main(String[] args) throws IOException, InterruptedException {
SocketReader reader = new SocketReader();
Thread thread = new Thread(reader);
thread.start();
Thread.sleep(1000);
reader.shutdown();
}
}
|
Note that the Runnable
object prevents itself from being run in multiple threads using an isRunning()
flag. If one thread tries to invoke run()
after another thread has already done so, the method will exit with an exception. This exception is not recoverable, as it indicates a bug in the proper usage of this class, and hence, it may be uncheckedan unchecked exception is thrown.
Noncompliant Code Example (blocking IO, interruptible)
This noncompliant code example uses thread interruption to indicate when that it is safe to shutdown the thread should shut down, as suggested above. However, this does not help in terminating is not useful because the thread because it is blocked on some network IO as a consequence of using the readLine()
method. Network I/O is not responsive to thread interruption.
...
This method interrupts the current thread, however, it only stops the thread because the thread logic code polls the interrupted flag using the method Thread.interrupted()
, and shuts down the thread when it is interrupted. Invoking the interrupt()
method of a thread that is blocked because of a java.nio.channels.Selector
also causes the thread to awaken.
...
The doSomething()
method of class PoolService
submits the task to a thread pool. It carries out the task and if an exception results during the execution of the code in the try
block, it interrupts the thread in as an attempt to cancel it.
Code Block | ||
---|---|---|
| ||
class PoolService { private final ExecutorService pool; public PoolService(int poolSize) { pool = Executors.newFixedThreadPool(poolSize); } public void doSomething() throws InterruptedException { Thread thread = new Thread(new Task()); try { pool.submit(thread); // ... } catch(Throwable t) { thread.interrupt(); // Forward to handler } } } |
...