关于ThreadLocal,java中有一个很相似的对比机制:clone.
他们的思想都是,给当前的线程/方法一个本地变量的copy,各个线程/方法虽然看起来是共享了一个变量,但相互之间并不干扰交互。
ThreadLocal是非常轻量级的保证线程安全的机制,不涉及锁,不涉及同步阻塞。完全是线程内部的一个变量。
那有的同学可能会问,既然这样干嘛还要设计成类的成员变量,直接在方法里面声明然后在方法之间传递不就好了。这样其实完全可以,但是相对来说代码结构会更加复杂,不利于后期的维护,我们来看一个ThreadLocal的例子:
- public class ConnectionManager {
- /** 线程内共享Connection,ThreadLocal通常是全局的,支持泛型 */
- private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
- public static Connection getCurrConnection() {
- // 获取当前线程内共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判断连接是否可用
- if(conn == null || conn.isClosed()) {
- // code : 创建新的Connection赋值给conn
- // code : 保存Connection
- threadLocal.set(conn);
- }
- } catch (SQLException e) {
- }
- return conn;
- }
- /**
- * 关闭当前数据库连接
- */
- public static void close() {
- // 获取当前线程内共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判断是否已经关闭
- if(conn != null && !conn.isClosed()) {
- // 关闭资源
- conn.close();
- // 移除Connection
- threadLocal.remove();
- conn = null;
- }
- } catch (SQLException e) {
- // 异常处理
- }
- }
- }
这是ThreadLocal应用的一个典型场景,大家可以琢磨一下两个问题:
1.如果不用ThreadLocal会怎么样?
2.如果不用ThreadLocal该怎么做?
如果最后你觉得在这种场景下ThreadLocal是最好的选择那么你基本就理解了ThreadLocal和它的使用场景。
接下来看一下Threadlocal的内部实现原理。
如果看过Thread和ThreadLocal源码的同学会发现,在Thread类内部有一个ThreadLocal.ThreadLocalMap这样的一个成员变量。在调用ThreadLocal的set/get时,程序会根据当前线程来获取对应的ThreadLocalMap,即Thread对象的ThreadLocal.ThreadLocalMap这个表,然后把值放入该Map中,即这个值是在线程内部而非ThreadLocal内部。这样在一个Thread对象里可以存放多个TheadLocal对象。