Skip navigation.
Home

java.lang.ThreadLocal

I hadn't previously had a reason to use java.lang.ThreadLocal, but I used it recently to add multi-threaded capabilities to a previously single-threaded application...

The application I modified is a basic batch maintenance JDBC type of stand-alone application that reads a text file and updates a database. In order to speed things up, the application was parallelized (if that is a word).

The problem was that the DB2 java.sql.Connection object (which was being retrieved from a custom factory) was not thread-safe. So I opted to use an individual Connection per thread. But how to implement this strategy?

I could have used a connection pool (FOSS or rolled) to help out, but there were a bunch of reasons why I didn't, here's a sampling:

  • The app is small and lean. Adding 3rd party pooling would be considered bloat, writing one myself would be a waste of time.
  • No sharing benefit; one app runs per JVM. If the system were deployed on an app server, where multiple apps could benefit from the same pool, the centralized management might be worth it.

I chose to wrap the Connection in ThreadLocal instead. Then redirect all calls for a connection (in the factory) to ThreadLocal.get().

The class snippet below doesn't really work but it illustrates the point..


public static Connection getConnection() {
  return (Connection) conn.get();
}

private static ThreadLocal conn = new ThreadLocal() {
  public Object initialValue() {
    String driverClass = "whatever";
    try {
      Class.forName(driverClass);
      Connection con = 
        DriverManager.getConnection("connectionURL",
          "user", "password");
      con.setReadOnly(true);
      con.setAutoCommit(false);
      return con;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
};

It worked like a champ.. every thread that called getConnection() got a different Connection and the threads could do their work independently. Eye-wink

avoid to cast

Hi Matt,
with subclassing it should be possible to avoid the cast in getConnection-method.
Sorry but I didn´t get it with generic-brackets (html-tags).
ThreadLocal is a generic class. Smiling

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionThreadLocal extends ThreadLocal(Connection){

public Connection initialValue(){
String driverClass = "";
try{
Class.forName(driverClass);
Connection con = DriverManager.getConnection("", "", "");
return con;
}catch(Exception e){

}
return null;
}

}

private static ConnectionThreadLocal conn = new ConnectionThreadLocal();

public static Connection getConnection(){
return conn.get();
}