ThreadLocal
出现的原因
与JDBC事务相关,在开启事务的时候,需要获取一个数据库的连接,在执行具体的sql语句的时候,为了把sql交给一个连接,又需要从数据库连接池中再拿一个连接。因此,有可能事务和具体sql语句的执行是不在同一个连接当中的,这就会导致事务失效。
作用
为每个线程提供一个独立的变量副本,把这个变量副本和线程进行强关联,需要使用的时候可以从ThreadLocal中直接拿变量副本。
这么做的好处是多个线程执行的时候,就不需要去抢占线程了,直接用自己的变量副本就好了。因为它是给每个线程单独分配一个变量,因此也能保证线程安全。
与synchronized的区别
Synchronized是一把锁,把所有对变量的访问控制起来,任何时候,都只能有一个线程对这个变量进行访问
ThreadLocal觉得这样效率不行,因此给每个线程单独分配一个变量,具体是通过ThreadLocalMap来存放线程中的变量副本。
使用方法
Void set(value) 设置当前线程的局部变量值
get() 获取当前线程所对应的线程局部变量
remove() 移除当前线程所对应的线程局部变量
InitalValue() 获取该线程局部变量的初始值
ThreadLocalMap与HashMap之间的区别
Hash冲突:10000个数要放去1000个桶之中,也就是说最少有一个桶要放多个数据,这样就产生了Hash冲突,本质上是压缩映射。
HashMap中的解决方法链地值法也就是用一张链表将这些数据存储下来;1.8之后,数据大于8会转换成红黑树
ThreadLocalMap解决Hash冲突的方法是开放定址法。简单点说就是一一映射的不存在一个桶对应多个数
实现思想
在每一个线程内部产生ThreadLocalMap成员变量,其实就是Map的实现,key是Entry[]也就是ThreadLocal本身,value就是要存放的变量副本
内存泄露
内存泄露:应该被回收的内存没有被回收
ThreadLocal会产生内存泄露的原因是因为ThreadLocalMap中的key对ThreadLocal是弱引用,当发生GC时key对应的ThreadLocal对象在堆中的内存会被回收,但是value对应的变量副本依然存在
解决办法:手动加一个remove()
强/弱引用
强引用:GC发生时,不会被垃圾回收器回收 例如: Object o = new Object()
WeakReference<> 弱引用:GC发生时,会被垃圾回收器回收