Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed the NCE/CS from socket to JDBC...common use case for thread-local

...

This method interrupts the current thread, however, it only stops the thread because the thread logic polls the interrupted flag using the method Thread.interrupted(), and shuts down when it is interrupted.

Noncompliant Code Example (

...

Connection per thread)

This noncompliant code example shows a thread-safe variant of the SocketReader class DBConnector that creates a Socket JDBC connection per thread, that is, the socket connection belonging to one thread is not shared amongst multiple threads. This is a common scenario in applications that must place requests to several servers simultaneously, without using any lockingby other threads.

Code Block
bgColor#FFcccc

// Thread-safe SocketReader
public class SocketReaderDBConnector implements Runnable {
  private final String hostquery;
  private final int port;

  SocketReaderDBConnector(String host, int portquery) {
    this.hostquery = hostquery;
    this.port = port;
  }
	
  public void run() {
    Socket socket = nullConnection con;
    try {
      socketcon = new Socket(host, port);
    } catch (UnknownHostException e) {
      // Forward to handler	DriverManager.getConnection("jdbc:myDriver:name", "username","password");  
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery(query);
    } catch (IOExceptionSQLException e) {
      // Forward to handler
    }
    // Do... some
 useful work
}  }
}

This design does not permit a client to close the socket when a cancel a task by closing it if the corresponding thread is blocked , or is performing some time consuming activityon a long running activity such as a join query. Furthermore, it is important to provide a mechanism to close connections to prevent thread starvation caused because of the limited number of database connections available in the pool. Similar task cancellation mechanisms are required when using objects local to a method, such as sockets.

Compliant Solution (ThreadLocal)

This compliant solution uses a ThreadLocal wrapper around the socket connection so that a thread that calls initialValue() obtains a unique socket connection instance. The advantage of this approach is that a shutdownSocketshutdownConnection() method can be provided so that clients external to the class can also shutdown close the socket connection when it the corresponding thread is blocked, or is performing some time consuming activity.

Code Block
bgColor#ccccff
class SocketReaderDBConnector implements Runnable {
  privatefinal staticString ThreadLocal<Socket>query;
 connectionHolder = new ThreadLocal<Socket>
  DBConnector(String query) {
    this.query = query;
  }
	
  private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
    SocketConnection socketconnection = null;
    @Override public SocketConnection initialValue() {		
      try {
	connection = DriverManager.getConnection
      socket  = new Socket("defaultHostjdbc:driver:name", 25"username","password"); // 25	 is the default port to connect to
      } catch (UnknownHostException e) {
      	   // Forward to handler	
      } catch (IOExceptionSQLException e) {
        // Forward to handler
      }
      return socketconnection;
    }
		
    @Override public void set(SocketConnection sockcon) {
      if(sockconnection == null) { // Shuts down socket when null value is passed 		       
        try {
	  	  socketconnection.close();
        } catch (IOExceptionSQLException e) {
 	          // Forward to handler	 
        }
 	       		     } else {
      } else socket{
 = sock; // Assigns Socket with caller specifiedconnection hostname= andcon; port
      }
    }
  };

  public static SocketConnection getSocketConnectiongetConnection() {
    return connectionHolder.get();
  }

  public static void shutdownSocketshutdownConnection() { // Allows client to close socket anytime
    connectionHolder.set(null);
  }

  public void run() {
    SocketConnection socketdbConnection = getSocketConnectiongetConnection();
    // Do some useful workStatement stmt;
    try {
      stmt = dbConnection.createStatement();		
      ResultSet rs = stmt.executeQuery(query);
    } catch (SQLException e) {
      // Forward to handler	 
    }    
    // ...
  }
}

Risk Assessment

Trying to force thread shutdown can result in inconsistent object state and corrupt the object. Critical resources may also leak if cleanup operations are not carried out as required.

...