⼀、什么是ThreadLocal
声明:本⽂使⽤的是JDK 1.8
⾸先我们来看⼀下JDK的⽂档介绍:
结合我的总结可以这样理解:ThreadLocal提供了线程的局部变量,每个线程都可以通过 set() 和get() 来对这个局部变量进⾏操作,但不会和其他线程的局部变量进⾏冲突,实现了线程的数据隔离简要⾔之:往ThreadLocal中填充的变量属于当前线程,该变量对其他线程⽽⾔是隔离的。
⼆、为什么要学习ThreadLocal?
从上⾯可以得出:ThreadLocal可以让我们拥有当前线程的变量,那这个作⽤有什么⽤呢???
2.1管理Connection
最典型的是管理数据库的Connection:当时在学JDBC的时候,为了⽅便操作写了⼀个简单数据库连接
池,需要数据库连接池的理由也很简单,频繁创建和关闭Connection是⼀件⾮常耗费资源的操作,因此需要创建数据库连接池~
那么,数据库连接池的连接怎么管理呢??我们交由ThreadLocal来进⾏管理。为什么交给它来管理呢??ThreadLocal能够实现当前线程的操作都是⽤同⼀个Connection,保证了事务!
当时候写的代码:
同样的,Hibernate对Connection的管理也是采⽤了相同的⼿法(使⽤ThreadLocal,当然了Hibernate的实现是更强⼤的)
2.2避免⼀些参数传递
避免⼀些参数的传递的理解可以参考⼀下Cookie和Session:
每当我访问⼀个⻚⾯的时候,浏览器都会帮我们从硬盘中找到对应的Cookie发送过去。浏览器是⼗分聪明的,不会发送别的⽹站的Cookie过去,只带当前⽹站发布过来的Cookie过去浏览器就相当于我们的ThreadLocal,它仅仅会发送我们当前浏览器存在的Cookie(ThreadLocal的局部变量),不同的浏览器对Cookie是隔离的(Chrome,Opera,IE的Cookie是隔离的【在Chrome登陆了,在IE你也得重新登陆】),同样地:线程之间ThreadLocal变量也是隔离的....
那上⾯避免了参数的传递了吗??其实是避免了。Cookie并不是我们⼿动传递过去的,并不需要写
<input name= cookie/> 来进⾏传递参数...
在编写程序中也是⼀样的:⽇常中我们要去办理业务可能会有很多地⽅⽤到身份证,各类证件,每次我
们都要掏出来很麻烦
⽽如果⽤了ThreadLocal的话,ThreadLocal就相当于⼀个机构,ThreadLocal机构做了记录你有那么多张证件。⽤到的时候就不⽤⾃⼰掏了,问机构拿就可以了。
在咨询时的时候就告诉机构:来,把我的身份证、房产证、学⽣证通通给他。在办理时⼜告诉机构:来,把我的身份证、房产证、学⽣证通通给他。...
这样是不是⽐⾃⼰掏⽅便多了。
当然了,ThreadLocal可能还会有其他更好的作⽤,如果知道的同学可在评论留⾔哦~~~
三、ThreadLocal实现的原理
想要更好地去理解ThreadLocal,那就得翻翻它是怎么实现的了~
⾸先,我们来看⼀下ThreadLocal的set()⽅法,因为我们⼀般使⽤都是new完对象,就往⾥边set对象了
上⾯有个ThreadLocalMap,我们去看看这是什么?
通过上⾯我们可以发现的是ThreadLocalMap是ThreadLocal的⼀个内部类。⽤Entry类来进⾏存储
我们的值都是存储到这个Map上的,key是当前ThreadLocal对象!
如果该Map不存在,则初始化⼀个:
如果该Map存在,则从Thread中获取!
Thread维护了ThreadLocalMap变量
从上⾯⼜可以看出,ThreadLocalMap是在ThreadLocal中使⽤内部类来编写的,但对象的引⽤是在
Thread中!
于是我们可以总结出:Thread为每个线程维护了ThreadLocalMap这么⼀个Map,⽽ThreadLocalMap的key是LocalThread对象本身,value则是要存储的对象有了上⾯的基础,我们看get()⽅法就⼀点都不难理解了:
3.1ThreadLocal原理总结
1. 每个Thread维护着⼀个ThreadLocalMap的引⽤
2. ThreadLocalMap是ThreadLocal的内部类,⽤Entry来进⾏存储
3. 调⽤ThreadLocal的set()⽅法时,实际上就是往ThreadLocalMap设置值,key是ThreadLocal对
象,只是传递进来的对象
4. 调⽤ThreadLocal的get()⽅法时,实际上就是往ThreadLocalMap获取值,key是ThreadLocal对象
5. ThreadLocal本身并不存储值,它只是作为⼀个key来让线程从ThreadLocalMap获取value。
正因为这个原理,所以ThreadLocal能够实现“数据隔离”,获取当前线程的局部变量值,不受其他线程
影响