ThreadLocal实现原理和使用场景
2022-12-13 11:09 杭伟 阅读(99) 评论(0) 编辑 收藏 举报ThreadLocal是线程本地变量,每个线程中都存在副本。
实现原理:
每个线程中都有一个ThreadLocalMap,而ThreadLocalMap中的key即是ThreadLocal。
内存泄漏:
ThreadLocal变量存储在栈内存中,对应对象存储在堆内存中,这个指向是强引用关系。
同样,ThreadLocalMap变量存储在栈内存中,对应对象key-value存储在堆内存中,也是强引用关系。同时map中的key也指向了threadlocal。
如果ThreadLocal变量被置为空,但是map仍存在引用,会导致堆中的对象无法释放,java已将map中的key优化为弱引用(WeakReference)。
但是value本身也存在强引用的关系,value并不会被释放,所以依然存在内存泄漏问题。
解决方法是,手动调用threadlocal的remove方法。
使用:
1 public class Main { 2 private static ThreadLocal<Integer> tl = new ThreadLocal<>(); 3 public static void main(String[] args) throws InterruptedException{ 4 CountDownLatch c = new CountDownLatch(1); 5 ThreadPoolExecutor tpe = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, 6 new ArrayBlockingQueue<>(3)); 7 tpe.execute(new Runnable() { 8 @Override 9 public void run() { 10 System.out.println(Thread.currentThread().getName()); 11 System.out.println(tl.get()); 12 tl.set(1); 13 System.out.println(tl.get()); 14 tl.remove(); 15 c.countDown(); 16 } 17 }); 18 tpe.execute(new Runnable() {//模拟 19 @Override 20 public void run() { 21 try{c.await();}catch (InterruptedException e){};//让第一个线程先执行 22 System.out.println(Thread.currentThread().getName()); 23 System.out.println(tl.get()); 24 tl.set(2); 25 System.out.println(tl.get()); 26 tl.remove(); 27 } 28 }); 29 tpe.shutdown(); 30 } 31 }
应用场景:
1,Spring多数据源配置的切换;
2,Spring事务注解的实现;
3,日志框架slf4j中的MDC类的实现
待更多补充。
作者:hangwei
出处:http://www.cnblogs.com/hangwei/
关于作者:专注于开源平台,分布式系统的架构设计与开发、数据库性能调优等工作。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
如果您觉得文章对您有帮助,可以点击文章右下角“推荐”一下。您的鼓励是作者坚持原创和持续写作的最大动力!