以前一直以为ThreadLocal很复杂, 只知道它的功能大概是将一个对象邦定到一个线程当中或者多个线程当中, 使得每个线程都使用同样一个对象。
举例说明:
public class HibernateSessionFactory {
private static final ThreadLocal threadLocal = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null) {
if (sessionFactory == null) {
try {
cfg.configure(CONFIG_FILE_LOCATION);
sessionFactory = cfg.buildSessionFactory();
}
catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
...
}
可以看到currentSession()方法每次返回的对象都是线程唯一。
其实ThreadLocal的实现不难,在看它的源代码之前,我想到的实现方案大概是,通过Thread.currentThread()获得当前线程,然后通过封装将待绑定的对象绑定到currentThread()上。
事实上,sun的实现方案也是大概如此。
可以看看ThreadLocal的get()方法的代码:
public Object get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
return map.get(this);
// Maps are constructed lazily. if the map for this thread
// doesn't exist, create it, with this ThreadLocal and its
// initial value as its only entry.
Object value = initialValue();
createMap(t, value);
return value;
}
ThreadLocalMap就是上面提到的那个封装Thread的对象。
值得注意的是: return map.getI(this);
可见ThreadLocal在set()和get()的时候需要保持为同一份对象的引用,才能保证能够正确地取出绑定的对象。
通过在自己的class当中将ThreadLocal设置为static的形式即可。