到底什么是ThreadLocal?
先从现实来看,如果我想让一份数据不会被并发访问或者修改,大约有两个办法,第一就是加锁,保证永远只有一个人来修改数据。第二个方法就是每个线程只操作自己的数据,把数据隔离 开。第一个方法就是类似synchorized,lock的概念,第二个就是threadlocal。
先看一下基本结构,Thread类有一个ThreadLocalMap,localmap的key就是threadlLocal,ThreadLocal里有静态类localmap。。。真绕啊~我们先不管这些,先找个简单的图来看
这里我们有一个静态变量threadLocal,开一个线程往里面set了一个值,他会创建一个threadlLocalMap
通过这个代码可以看到,他去那个线程看一下有没有map,没有就到那个线程创建一个,好,这里我们清楚了,每个线程都会有一个threadLocalMap,这个map的key就是threadLocal,值是value。这个不难理解,我们存储的值,实际都到那个线程的map里了。
假如我们系统需要获取用户身份,那我们可以在拦截器最前面设置,先获取用户身份,再扔到threadlocal,那无论走到哪一步,都能直接get到用户身份了,岂不是很方便?每个用户线程调用get返回的都是自己信息。
这里有什么问题吗?有,一来是内存泄漏问题。localmap的key虽然是弱引用,可以被回收,但是value可不是,假设你的是一个线程池,被复用了,这个线程肯定还在,key没了是null,value什么时候被释放呢?当然设计者判断了如果key是null,就会删除你的value。还有一种问题,线程复用了,假设你由于某种骚操作,第二个复用线程没走set,那get到的就是之前的线程留下来的信息。
假设我们全局只有一个threadlocal,可能遇到的问题就是线程被复用的时候可能数据会串,比如上一个线程丢的,被下一个线程取到了值。如果有多个threadlocal的时候,则可能遇到内存泄漏,因为每个thread的map有多个entry,set的时候会随机清理key为空的,remove会一定清理,但是起码这个是泄露了。但问题影响也不大。