来源:https://gitbook.cn/books/5abef415a1a5b4123501526e/index.html
ThreadLocal 是在 JDK 包里面提供的,它提供了线程本地变量,也就是如果你创建了一个 ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作的自己本地内存里面的变量,从而避免了线程安全问题,创建一个 ThreadLocal 变量后每个线程会拷贝一个变量到自己本地内存。
同一个 ThreadLocal 变量在父线程中设置值后,在子线程中是获取不到的。
为了解决上面的问题,InheritableThreadLocal 应运而生,InheritableThreadLocal 继承自 ThreadLocal,提供了一个特性,就是子线程可以访问到父线程中设置的本地变量。
ThreadLocalRandom 类是 JDK7 在 JUC 包下新增的随机数生成器,它解决了 Random 类在多线程下的不足。
每个 Random 实例里面只有一个原子性的种子变量用来记录当前种子的值,当要生成新的随机数时,需要根据当前种子计算新种子并更新原子变量。
多线程下使用单个 Random 实例生成随机数时,多个线程同时计算新种子时会竞争同一个原子变量的更新操作,由于原子变量的更新是 CAS 操作,同时只有一个线程会成功,所以会造成大量线程自旋重试,这会降低并发性能。
所以 ThreadLocalRandown 应运而生。
ThreadLocalRandom 使用 ThreadLocal 的原理,让每个线程内持有一个本地的种子变量,该种子变量只有在使用随机数时候才会被初始化,多线程下计算新种子时候是根据自己线程内维护的种子变量进行更新,从而避免了竞争。
Spring 可以在 XML 里面配置 Bean 的时候可以指定 scope 属性来配置该 Bean 的作用域为 singleton、prototype、request、session 等。
其中作用域为 request 的实现原理就是使用 ThradLocal 实现的。
如果想让某个 Bean 拥有 web 的某种作用域,除了需要配置 Bean 相应的 scope 属性外,还必须在 web.xml 中进行如下配置:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>