啸羽程序园
JAVA教程学习项目笔记首页

ThreadLocal是什么、深入理解ThreadLocal原理和应用场景

ThreadLocal熟悉而又陌生的一个变量。
ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。
ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。简单来说就是同一个变量在不同线程里有各自的副本,更改使用互不影响。
那么,ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中定义了一个ThreadLocalMap,每一个Thread中都有一个该类型的变量——threadLocals——用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
ThreadLocal的原理
在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:
public class ThreadLocal
private Map values = Collections.synchronizedMap(new HashMap());
public Object get()
{
Thread curThread = Thread.currentThread();
Object o = values.get(curThread);
if (o == null && !values.containsKey(curThread))
{
o = initialValue();
values.put(curThread, o);
}
values.put(Thread.currentThread(), newValue);
return o ;
}
public Object initialValue()
{
return null;
}
}
看样子很复杂,其实理解透彻了很简单,一个map,key是当前线程,value是当前线程的变量(就是你想要的那个多线程互不影响的变量副本)
应用场景:
比如应用于数据库连接、session管理等等。

数据库连接:

Class A implements Runnable{
    private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
        public Connection initialValue() {
                return DriverManager.getConnection(DB_URL);
        }
    };

    public static Connection getConnection() {
           return connectionHolder.get();
    }
}

Session管理

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是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
Hi, I’m shen, 啸羽