Thursday, June 08, 2006

java.lang.ThreadLocal

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.

(http://mattfleming.com/node/118)

No comments: