通常在多线程中,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
实现线程本地类其实不难:以当前线程为key,要保存的对象为value
public class ThreadLocalSample {
private Map map = Collections.synchronizedMap(new HashMap());
public void set(Object value) {
map.put(Thread.currentThread(), value);
}
public Object get() {
Object value = map.get(Thread.currentThread());
return value;
}
}
ThreadLocal可用在Servlet的过滤器中,比如:每一个请求都由一个Connection来操作数据库,由于Servlet只有一个实例,所以应该是每个线程用一个连接,而不是所有线程用一个Connection,因此需要用到ThreadLocal类;由于Servlet是在Filter链的调用中点执行,即Filter1->Filter2->...->Servlet->Filter2->Filter1,因此:可以用一个Filter,在这个Filter调用下一个Filter前初始化连接,并将其放入ThreadLocal中,在调用又回到这个Filter时,得到连接并关闭。
代码如下:
public class TransactionManageFilter implements Filter {
private FilterConfig config;
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
public void destroy() {
config = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
Connection conn = ConnectionManager.currentConnection();
try {
conn.setAutoCommit(false);
chain.doFilter(request, response, chain);
conn.commit();
} catch (Exception e) {
conn.rollback();
} finally {
try {
conn.setAutoCommit(true);
conn.close();
ConnectionManager.removeConnection();
} catch (Exception e) {}
}
}
}
public class ConnectionManager {
private static ThreadLocal currConn = new ThreadLocal();
public static Connection currentConnection() {
Object obj = currConn.get();
if (obj != null) {
return (Connection)obj;
} else {
Connection conn = ConnectionFactory.getConnection();
currConn.set(conn);
return conn;
}
}
public static void removeConnection() {
Object obj = currConn.get();
if (obj != null) {
currConn.set(null);
}
}
}