java线程变量threadLocal工作原理及遇到的坑

前天使用了ThreadLocal作为线程变量,用来存储一些用户的登陆信息。每一个请求进来,服务器会创建一个线程,并为这个线程开辟一段内存空间,用来存储线程变量。使用ThreadLocal可以很容易的实现这点。

java线程变量threadLocal工作原理及遇到的坑_第1张图片

这里当我们需要保存用户ID的时候,就将用户id放到ThreadLocal存储的map中,当需要使用用户ID的时候,就从ThreadLocal中取出来即可,所以每个请求应该都能取到各自的用户登录信息。

但是实际测试的时候却发现一个问题,当同时2个线程在同一瞬间执行的时候,线程变量会有错位的情况,于是调试了一下代码,发现即使当前没有执行设置线程变量,paramMap理应是空,但是依然被初始化了,原来是我们将paramMap修饰成static final,所以每个线程获取到的其实是同一个paramMap。

再看ThreadLocal源码

java线程变量threadLocal工作原理及遇到的坑_第2张图片

可以发现,jvm维护了一个全局map ThreadLocalMap,ThreadLocalMap会根据以每个线程对象为key,set进去的对象为value,维护全部的线程变量。所以每次get的时候是根据当前线程对象从ThreadLocalMap中获取到相应的线程变量而已。

因此,我们设置线程变量的时候,应该为每个线程变量单独初始化,每个线程变量应该存在于线程自己的工作内容中。

另外,springmvc 底层会维护一个线程池,线程复用的时候可能会导致不同请求线程变量是一样的,应该注意小心避免产生并发问题

你可能感兴趣的:(java线程变量threadLocal工作原理及遇到的坑)