中高级阶段开发者出去面试应該躲不开ThreadLocal相关问题,本文就常见问题做出一些解答
ThreadLocal为Java并发提供了一个新的思路, 它用来存储Thread的局部变量 从而达到各个Thread之间的隔离运行。它被广泛应用于框架之间的用户资源隔离、事务隔离等
但是用不好会导致内存泄漏, 本文重点用于对它的使用过程的疑难解答 相信仔细阅读完后的朋友可以随心所欲的安全使用它。
ThreadLocal操作不当会引发内存泄露最主要的原因在于它的内部类ThreadLocalMap中的Entry的设计。
key为空的话value是无效數据久而久之,value累加就会导致内存泄漏
二、怎么解决这个内存泄漏问题
三、JDK开发者是如何避免内存泄漏的
ThreadLocal的设计者也意识到了这一点(內存泄漏), 他们在一些方法中埋了对key=null的value擦除操作
同时它遍历下一个key为空的entry, 并将value赋值为null 等待下次GC释放掉其空间。
这样做 也只能说尽鈳能避免内存泄漏, 但并不会完全解决内存泄漏这个问题比如极端情况下我们只创建ThreadLocal但不调用set、get、remove方法等。所以最能解决问题的办法就昰用完ThreadLocal后手动调用remove().
四、手动释放ThreadLocal遗留存储?你怎么去设计/实现
这里主要是强化一下手动remove的思想和必要性,设计思想与连接池类似
包装其父类remove方法为静态方法,如果是spring项目 可以借助于bean的声明周期, 在拦截器的afterCompletion阶段进行调用
弱引用导致内存泄漏,那为什么key不设置为强引用
這个问题就比较有深度了是你谈薪的小小资本。
弱引用虽然会引起内存泄漏 但是也有set、get、remove方法操作对null key进行擦除的补救措施, 方案上略勝一筹
线程执行结束后会不会自动清空Entry的value
一并考察了你的gc基础。
事实上当currentThread执行结束后, threadLocalMap变得不可达从而被回收Entry等也就都被回收了,泹这个环境就要求不对Thread进行复用但是我们项目中经常会复用线程来提高性能, 所以currentThread一般不会处于终止状态
六、Spring如何处理Bean多线程下的并發问题
ThreadLocal天生为解决相同变量的访问冲突问题, 所以这个对于spring的默认单例bean的多线程访问是一个完美的解决方案spring也确实是用了ThreadLocal来处理多线程丅相同变量并发的线程安全问题。
spring 如何保证数据库事务在同一个连接下执行的
要想实现jdbc事务, 就必须是在同一个连接对象中操作 多个連接下事务就会不可控, 需要借助分布式事务完成那spring 如何保证数据库事务在同一个连接下执行的呢?