...
Code Block | ||
---|---|---|
| ||
class BadStop implements Runnable { public void run() { try { Thread.currentThread().sleep(1000); } catch(InterruptedException ie) { // Not executed System.out.println("Performing cleanup"); } finally { // Not executed System.out.println("Closing resources"); } System.out.println("Done!"); } } class Controller { public static void main(String[] args) { Thread t = new Thread(new BadStop()); t.start(); t.interrupt(); // Artificially induce an InterruptedException t.stop(); // Force thread cancellation } } |
Wiki Markup |
---|
The {{Thread.interrupt()}} method is frequently used to awaken a blocked thread before it can be stopped. It awakens threads that are blocked on {{wait()}} methods of class {{Object}}, {{join}} and {{sleep}} methods of class {{Thread}}. In these cases, the thread's interrupt status is cleared and it receives an {{InterruptedException}}. If the thread is blocked on I/O operations upon an interruptible channel, the channel is closed, the thread's status is set and the thread receives a {{ClosedByInterruptException}}. Similarly, a thread waiting on a selector also returns from the operation with its interrupted status set \[[API 06|AA. Java References#API 06]\]. |
Compliant Solution (1) (volatile
flag)
...
This noncompliant code example uses the advice suggested in the previous compliant solution. UnfortunatelyHowever, this does not help in terminating the thread because it is blocked on some network IO because as a consequence of using the readLine()
method. The boolean
flag trick does not work in such cases; a good alternative to end the thread is required.
Code Block | ||
---|---|---|
| ||
class StopSocket extends Thread { private Socket s; private volatile boolean done = false; public void run() { while(!done) { try { s = new Socket("somehost", 25); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); String s = null; while((s = br.readLine()) != null) { // Blocks until end of stream (null) } System.out.println("Blocked, will not get executed until some data is received. " + s); } catch (IOException ie) { // Forward to handler } finally { System.out.println("Closing resources"); done = true; } } } public void shutdown() throws IOException { done = true; } } class Controller { public static void main(String[] args) throws InterruptedException, IOException { StopSocket ss = new StopSocket(); Thread t = new Thread(ss); t.start(); Thread.sleep(1000); ss.shutdown(); } } |
A Socket
connection is not affected by the InterruptedException
that results with the use of the Thread.interrupt()
method. The boolean
flag solution does not work in such cases.
Compliant Solution
This compliant solution closes the socket connection, both using the shutdown()
method as well as the finally
block. As a result, the thread is bound to stop due to a SocketException
. Note that there is no way to keep the connection alive if the thread is to be cleanly halted immediately.
...