Noncompliant Code Example (Blocking I/O, Volatile Flag)
This noncompliant code example uses a volatile
done flag to indicate it whether is safe to shut down the thread, as suggested in THI05-J. Do not use Thread.stop() to terminate threads. However, when the thread is blocked on network I/O as a consequence of invoking the
readLine() method, it cannot respond to the newly set flag until the network I/O is complete. Consequently, thread termination may be indefinitely delayed.
Noncompliant Code Example (Blocking I/O, Interruptible)
This noncompliant code example is similar to the preceding example but uses thread interruption to shut down the thread. Network I/O on a
java.net.Socket is unresponsive to thread interruption.
Compliant Solution (Close Socket Connection)
This compliant solution terminates the blocking network I/O by closing the socket in the
shutdown() method. The
readLine() method throws a
SocketException when the socket is closed, consequently allowing the thread to proceed. Note that it is impossible to keep the connection alive while simultaneously halting the thread both cleanly and immediately.
shutdown() method is called from
finally block in
readData() executes and calls
shutdown() again, closing the socket for a second time. However, when the socket has already been closed, this second call does nothing.
When performing asynchronous I/O, a
java.nio.channels.Selector can be unblocked by invoking either its
close() or its
When additional operations must be performed after emerging from the blocked state, use a
boolean flag to indicate pending termination. When supplementing the code with such a flag, the
shutdown() method should also set the flag to false so that the thread can cleanly exit from the
Compliant Solution (Interruptible Channel)
This compliant solution uses an interruptible channel,
java.nio.channels.SocketChannel, instead of a
Socket connection. If the thread performing the network I/O is interrupted using the
Thread.interrupt() method while it is reading the data, the thread receives a
ClosedByInterruptException, and the channel is closed immediately. The thread's interrupted status is also set.
This technique interrupts the current thread. However, it stops the thread only because the code polls the thread's interrupted status with the
Thread.interrupted() method and terminates the thread when it is interrupted. Using a
SocketChannel ensures that the condition in the
while loop is tested as soon as an interruption is received, even though the read is normally a blocking operation. Similarly, invoking the
interrupt() method of a thread blocked on a
java.nio.channels.Selector also causes that thread to awaken.
Noncompliant Code Example (Database Connection)
This noncompliant code example shows a thread-safe
DBConnector class that creates one JDBC connection per thread. Each connection belongs to one thread and is not shared by other threads. This is a common use case because JDBC connections are intended to be single-threaded.
Database connections, like sockets, lack inherent interruptibility. Consequently, this design fails to support the client's attempts to cancel a task by closing the resource when the corresponding thread is blocked on a long-running query, such as a join.
Compliant Solution (
This compliant solution uses a
ThreadLocal wrapper around the connection so that a thread calling the
initialValue() method obtains a unique connection instance. This approach allows provision of a
cancelStatement() so that other threads or clients can interrupt a long-running query when required. The
cancelStatement() method invokes the
Statement.cancel() method cancels the query, provided the database management system (DBMS) and driver both support cancellation. It is impossible to cancel the query if either the DBMS or the driver fail to support cancellation.
By default, only one
Statementobject can be open at the same time. As a result, if the reading of one
ResultSetobject is interleaved with the reading of another, each must have been generated by different
This compliant solution ensures that only one
ResultSet is associated with the
Statement belonging to an instance, and, consequently, only one thread can access the query results.
Failure to provide facilities for thread termination can cause nonresponsiveness and DoS.
Section 24.3, "Stopping a Thread"
Chapter 7, "Cancellation and Shutdown"
Section 2.4, "Two Approaches to Stopping a Thread"
Java Thread Primitive Deprecation
Section 14.12.1, "Don't Stop"