什么是ThreadLocal
ThreadLocal提供了线程的局部变量,每个线程都可以通过set()和get()来对这个局部变量进行操作,但不会和其他线程的局部变量进行冲突,实现了线程的数据隔离。
应用场景
- 管理Connection
在学JDBC的时候,为了方便操作写了一个简单数据库连接池,需要数据库连接池的理由也很简单,频繁创建和关闭Connection是一件非常耗费资源的操作,因此需要创建数据库连接池。
那么,数据库连接池的连接怎么管理呢??我们交由ThreadLocal来进行管理。为什么交给它来管理呢??ThreadLocal能够实现当前线程的操作都是用同一个Connection,保证了事务! - 避免一些参数传递
每当我访问一个页面的时候,浏览器都会帮我们从硬盘中找到对应的Cookie发送过去。
浏览器是十分聪明的,不会发送别的网站的Cookie过去,只带当前网站发布过来的Cookie过去
浏览器就相当于我们的ThreadLocal,它仅仅会发送我们当前浏览器存在的Cookie(ThreadLocal的局部变量),不同的浏览器对Cookie是隔离的 - 在编写程序中也是一样的:日常中我们要去办理业务可能会有很多地方用到身份证,各类证件,每次我们都要掏出来很麻烦。
而如果用了ThreadLocal的话,ThreadLocal就相当于一个机构,ThreadLocal机构做了记录你有那么多张证件。用到的时候就不用自己掏了,问机构拿就可以了。
ThreadLocal实现原理
- set()方法
ThreadLocalMap是ThreadLocal的一个内部类。用Entry类来进行存储
我们的值都是存储到这个Map上的,key是当前ThreadLocal对象!
如果该Map不存在则初始化一个,否则就从Thread中获取。、每个Thread维护了一个ThreadLocalMap变量。
ThreadLocalMap是在ThreadLocal中使用内部类来编写的,但对象的引用是在Thread中!
Thread为每个线程维护了ThreadLocalMap这么一个Map,而ThreadLocalMap的key是LocalThread对象本身,value则是要存储的对象 - get()方法
内存泄漏
- 内存泄露:不再使用的对象和变量的空间不能被回收。时间久之后会浪费掉大量的内存空间。
- 强引用:无论任何情况下, 只要强引用关系还存在, 垃圾收集器就永远不会回收掉被引用的对象。
- 软引用:在系统将要发生内存溢出异常前, 会把这些对象列进回收范围之中进行第二次回收
- 弱引用:被弱引用关联的对象只能生存到下一次垃圾收集发生为止
- 虚引用:一个对象是否有虚引用的存在, 完全不会对其生存时间构成影响
和key是否是强弱引用无关,由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏。
想要避免内存泄露就要手动remove()掉!