关于ThreadLocal一点心得
防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,可以为使用相同变量的每个不同线程都创建不同的存储。(摘自Java编程思想)
摘自Thread源码:
package java.lang;
public class Thread implements Runnable {
/*
...
*/
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
每个Thread都有一个自有的ThreadLocalMap。
再看下ThreadLocal下的ThreadLocalMap源码:
public class ThreadLocal<T> {
public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }
/*
...
*/
static class ThreadLocalMap {
/*
...
*/
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
}
}
ThreadLocalMap是一个类似于Map静态内部类。key值为ThreadLocal,value为一个对象。
从源码中可以看出什么是ThreadLocal,它主要干什么:
ThreadLocal是对变量的线程本地存储。每个Thread都有一个ThreadLocal.ThreadLocalMap属性。ThreadLocalMap中key值是ThreadLocal,value是存储的对象值。
ThreadLocal 的用途是什么?
1、数据库连接
private static final ThreadLocal<DBSession> tl = new ThreadLocal<DBSession>();
private Connection conn = null;
public static DBSession getCurrent() throws SQLException {
DBSession result = tl.get();
if(result == null){
result = new DBSession();
tl.set(result);
}
return result;
}
private DBSession() throws SQLException {
conn = DBFactory.newConnection();
conn.setAutoCommit(DBFactory.isAutoCommit());
}
2、Session管理(mybatis连接)
private static SqlSessionFactory factory;
private static final ThreadLocal<SqlSession> tl = new ThreadLocal<SqlSession>();
/**
* 得到与当前线程绑定的 SqlSession对象
* 如果当前线程已经绑定了SqlSession对象,则返回该对象,否则打开新的SqlSession对象,绑定到当前线程,并返回
* @return SqlSession 对象
*/
public static SqlSession getCurrent(){
SqlSession result = tl.get();
if(result == null){
result = factory.openSession();
tl.set(result);
}
return result;
}
/**
* 关闭与当前线程绑定的 SqlSession 对象
*/
public static void closeCurrent(){
SqlSession session = tl.get();
if(session != null){
try{
session.close();
tl.remove();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
参考文章: