ThreadLocal
ThreadLocal
类中维护ThreadLocalMap
,用于存储每个线程的变量副本。ThreadLocalMap
中Entry
的键为线程对象,而值为对应线程的变量副本,Entry(ThreadLocal k, Object v)
。采用空间换时间。ThreadLocal
不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点:每个线程中都有一个自己的
ThreadLocalMap
类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。将一个共用的
ThreadLocal
静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap
中,然后在线程执行的各处通过这个静态ThreadLocal
实例的get()
方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
应用场景
最常见的
ThreadLocal
使用场景为:解决数据库连接、Session管理等。
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
Hibernate中典型的
ThreadLocal
的应用:
private static final ThreadLocal threadSession = new ThreadLocal();
public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}
ThreadLocal
内存泄漏的根源是:由于ThreadLocalMap
的生命周期跟Thread
一样长,如果没有手动删除对应key的value就会导致内存泄漏,而不是因为弱引用。避免内存泄漏:每次使用完
ThreadLocal
,都调用它的remove()
方法,清除数据。
示例
ThreadLocalTest
,ThreadLocalNoSetTest
// java.lang.Thread
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;