用ThreadLocal来优化下代码吧

简介: 用ThreadLocal来优化下代码吧

1.什么是ThreadLocal


先来看下JDK的注释:

47.png


简单翻译过来,就是说:


ThreadLocal提供了线程隔离的局部变量,通过get( )和set( )方法操作当前线程对应的变量,而且不会和其他线程冲突,实现了基于线程的数据隔离。


2.如何使用ThreadLocal进行优化


话不多说,基于我们开头的例子,我迫不及待地用ThreadLocal来优化一下。


2.1 构建基于ThreadLocal的上下文


定义一个SessionUser类,存储用户信息,包括用户id、用户名。

然后定义一个基于ThreadLocal的上下文SessionUserContext,代码如下所示。

48.png


2.2 信息存入ThreadLocal中


在我们的优化案例中,就是存入用户信息。


解析请求中的用户信息有很多方法。本文以HandlerIntercept为例,说明下MVC中的一种方式。


  • 实现HandlerIntercept接口
  • 重写preHandler方法
  • 解析HttpServletRequest,获取用户信息
  • 用户信息存于SessionUserContext


源码如下所示。

49.png


2.3 在需要的地方获取信息


原本需要传入CurrentUser的参数都可以去掉了。


在需要用户信息的时候,直接从SessionUserContext中获取即可。

50.png


哈哈,是不是看起来一下子清爽了很多。


可以在任何地方获取user信息,不再需要层层传递用户信息了。

51.jpg


3.ThreadLocal实现原理


上面我们已经知道了怎么通过ThreadLocal进行优化。


下面,我们要 知其然知其所以然,一起看看ThreadLocal实现原理吧。


3.1 set方法


Set方法应该是ThreadLocal的核心逻辑了。


主要三步:


  • 获取当前线程
  • 获取ThreadLocalMap对象
  • 如果ThreadLocalMap对象存在,则将当前线程对象作为key,要存储的对象作为value存到map中 如果ThreadLocalMap对象不存在,就调用creatMap( )进行创建

52.jpg


3.2 ThreadLocalMap是什么。


ThreadLocalMap是一个定义在ThreadLocal类内部的静态类,里面还定义了一个Entry类作为存储值的地方。


ThreadLocalMap的key是当前ThreadLocal对象,value是我们要存储的值(对象)。

53.png


调用creatMap的时候,就是新建一个ThreadLocalMap对象

54.jpg


同时,ThreadLocalMap在Thread类中作为一个属性存在。

55.png


每个线程Thread维护了ThreadLocalMap这么一个Map,这个map的key是LocalThread对象本身,value则是要存储的对象


3.3 get方法


Get方法就比较简单了,就是从map中取值的过程。

56.jpg


3.4 ThreadLocal小结


现在,让我们重新梳理一遍,看看ThreadLocal是如何实现变量的线程隔离的:


  • 每个Thread维护着一个ThreadLocalMap的引用
  • ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储,key是ThreadLocal对象,值是传递进来的对象
  • 调用ThreadLocal的get()/set()方法时,实际上就是以ThreadLocal对象为key,在ThreadLocalMap中读写value


4.实战要点


在一开始的优化设计中,不知道大家有没有注意到对ThreadLocal的remove调用。

57.jpg


这里就需要谈谈ThreadLocal使用时的,两个要点。尤其是在使用线程池的时候使用ThreadLocal。


4.1 避免内存泄露

58.png


在ThreadLocalMap介绍的时候,我们可以看到,ThreadLocalMap是Thread的一个属性。因此,ThreadLocalMap和Thread的生命周期是一样的。


如果没有手动删除对应的ThreadLocal的key,那么就会造成内存泄漏无法回收。尤其在线程池环境下,线程会被不断复用。


4.2 线程池避免重复线程变量影响


以上文优化案例为例。


在MVC中,每次请求进来会使用线程池复用线程。如果请求带了用户信息,那么就会重置ThreadLocal对应的用户信息,如果请求没有带用户信息,必须手动清除一下当前ThreadLocal对应的变量,否则后面使用过程中可能会造成混乱。

目录
相关文章
|
2月前
|
安全 Java 程序员
ThreadLocal详解,源码级的详解,快来学
从源码入手,20分钟快速掌握ThreadLocal的原理。
ThreadLocal详解,源码级的详解,快来学
|
4月前
|
存储 安全 Java
ThreadLocal原理讲解
ThreadLocal原理讲解
26 0
|
9月前
|
存储 Java
大厂是怎么用ThreadLocal?ThreadLocal核心原理分析
ThreadLocal**是Java中的一个线程本地变量类。它可以让每个线程都有自己独立的变量副本,而不会相互影响。
86 1
|
存储 算法 安全
ThreadLocal原理剖析
ThreadLocal原理剖析
165 0
|
Java 定位技术
ThreadLocal原理
经典八股文之ThreadLocal原理
151 0
|
缓存 安全 Java
如何使用ThreadLocal避免线程安全问题?
这篇文章是关于ThreadLocal的第二篇文章。 在上一篇文章,Yasin给大家介绍了什么是ThreadLocal,以及ThreadLocal的基本原理。 那在实际工作中,ThreadLocal一般用来做什么呢?今天我们以一个简单的应用场景为例,给大家介绍如何用ThreadLocal来帮助我们解决多线程的安全问题。
367 0
多线程 - 一篇带你理解 InheritableThreadLocal 作用
多线程 - 一篇带你理解 InheritableThreadLocal 作用
94 0
|
前端开发 Java 程序员
彻底读懂ThreadLocal与Synchronized区别(代码案例详解)
📝本篇用案例代码带初学者彻底读懂ThreadLocal与Synchronized区别!
135 0
彻底读懂ThreadLocal与Synchronized区别(代码案例详解)
|
安全 Java 数据库连接
ThreadLocal内存溢出代码演示和原因分析!(2)
ThreadLocal内存溢出代码演示和原因分析!(2)
95 0
ThreadLocal内存溢出代码演示和原因分析!(2)