作用
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢? JDK 中提供的ThreadLocal
类正是为了解决这样的问题。 ThreadLocal
类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal
类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
如果你创建了一个ThreadLocal
变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal
变量名的由来。他们可以使用 get()
和 set()
方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
ThreadLocal是一个线程本地变量,作用主要是做数据隔离。
ThreadLocal中填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的,每个线程维护自己的变量副本,多个线程互相不可见,因此多线程操作该变量不必加锁,适合不同线程使用不同变量值的场景;
应用场景----spring 事务
一个数据库对应n个线程,一个线程对应一个事务;Spring框架在【事务】开始时会给【当前线程】绑定一个JDBC Connection,整个事务过程都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性;
事务隔离级别:读未提交,读已提交,可重复读,串行化
spring 事务主要是 ThreadLocal 和 AOP(切面编程) 实现的;
ThreadLocalMap的【弱引用】及其引起的【内存泄露】,实际上,ThreadLocal内部已经为我们做了一定的防止内存泄漏的工作,如调用expungeStaleEntry()方法;
事务包中 TransactionSynchronizationManager 的源码如下:
ThreadLocal应用最佳实践
- 在ThreadLocal使用前后都调用remove清理,同时对异常情况也要在finally中清理
- ThreadLocal一般加static修饰,如果ThreadLocal不加static,则每次其所在类实例化时,都会有重复ThreadLocal创建。这样即使线程在访问时不出现错误也有资源浪费;