五分钟深入理解 ThreadLocal

内容分享1周前发布
2 0 0

如果把 ThreadLocal 改成 ThreadLocalVariable 或许更容易理解,和 Integer Double 一样,是基本数据类型的封装类型,只不过它是一个用在 Thread 内的 Variable,

在不同的线程中访问同一个 ThreadLocal 对象的 set 和 get 进行存取数据是不会相互干扰的。ThreadLocal就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)

五分钟深入理解 ThreadLocal

ThreadLocal 源码的数据类型

Java 常用的数据类型里,ThreadLocal 肯定是其中的一种,如果让你盲猜你会想到什么,我猜是个Map,目前我们看看源码,我盲搜Map关键字看出来什么?

五分钟深入理解 ThreadLocal

内部使用的是 Entry 数组,我就当HashMap使用。

ThreadLocal 的使用场景

可能许多人不知道 ThreadLocal 的使用场景,只是为了背面试题而背,这就尴尬了,工作中,只要有线程的地方就可以使用 ThreadLocal 就像使用 Integer 一样自然。

ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。

列如缓存用户登陆信息:

我有一个全局拦截器,在拦截器里校验每一次用户身份是否合法。

@Slf4j
@Service
public class UcRequestContext extends HandlerInterceptorAdapter {

	private static final ThreadLocal<SessionUser> SESSION_USER_THREAD_LOCAL = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        PermissionParamConfig permissionParamConfig = applicationContext.getBean(PermissionParamConfig.class);
	       
				// 构建 session 信息

				SessionUser session = new SessionUser()
				// 省略 session set 方法
				SESSION_USER_THREAD_LOCAL.set(session);
			
        return true;
    }

		@Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 清空session
				SESSION_USER_THREAD_LOCAL.remove();
    }

}

每次一请求开始,代表一个新的Thread创建,preHandle会创建一个 ThreadLocal 方法,

每次一请求结束,代表一个新的Thread创建,afterCompletion会销毁这个 ThreadLocal 里的session信息。

ThreadLocal 在 JDK 8 中 做了哪些升级


static class ThreadLocalMap {

				/**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
 }

可以看到 ThreadLocalMap 中的 Entry 继承了 WeakReference<ThreadLocal<?>>

为什么是弱引用呢?

使用弱引用的缘由在于,当没有强引用指向 ThreadLocal 变量时,它可被回收,从而避免上文所述 ThreadLocal 不能被回收而造成的内存泄漏的问题。

© 版权声明

相关文章

暂无评论

none
暂无评论...