【面试题】复习ThreadLocal面试题和原理

本文探讨了ThreadLocal在Java中的两种应用场景,强调了在多线程和线程池中的使用注意事项,特别是内存泄露问题。通过实例解释了如何正确使用ThreadLocal并避免内存泄漏,以及ThreadLocal内部的自动清理机制。
摘要由CSDN通过智能技术生成

ThreadLocal面试题

两种应用场景:

1、线程之间做数据隔离;
2、单个线程中做参数传递;

通常,在业务代码中,使用的是static的变量

这里需要理解,Thread中的Map,key是this,也就是ThreadLocal对象的指针哈希值
为什么使用完要remove掉,比如在线程池中,线程被反复使用,可能到期这个ThreadLocalMap变得非常的大,占用内存;

示例代码:

class UserContextHolder{
    public static ThreadLocal<User> holder = new ThreadLocal<>();
}

内存泄露怎么理解?

演示代码

public class Test {
	public static void main(String[] args) {
		ThreadLocal local = new ThreadLocal();
		local.set(new Test());
		local = null;
		// 手动触发GC,此时ThreadLocal被回收,那么value是否被回收呢?
		System.gc();
		// GC是异步执行的,主线程Sleep一会,等待对象回收
		ThreadUtil.sleep(1000);
	}

	// 对象被回收时触发
	@Override
	protected void finalize() throws Throwable {
		System.err.println("对象被回收...");
	}
}
https://juejin.cn/post/6932807532587810824

可以参考这个帖子
总结:
线程池的线程不会被回收;需要记得使用remove方法!
在这里插入图片描述
Entry中的Key设计为WeakReference的方式
在这里插入图片描述
一个对象可以被一个变量通过强引用的方式指向,也可以被另外一个变量通过若应用的方式指向;(这里要注意,引用是一个指针指向)
当这个对象只被若应用指向的时候,那么这个对象就会被回收,不管内存够不够使用;
如果这个ThreadLocal强引用没有了,只有弱引用,那么就会被回收,就成为了null值;
如果这个Entry对象的Key为了null,但是value还是存在,那么这个value就被泄露了

避免的方式,下面基本都是使用了第二点,所以可以认为不存在啊在这里插入图片描述

当然,就是使用不规范,ThreadLocal内部也做了一些优化,比如:
在这里插入图片描述
调用set()方法时,ThreadLocal会进行采样清理、全量清理,扩容时还会继续检查。
调用get()方法时,如果没有直接命中或者向后环形查找时也会进行清理。
调用remove()时,除了清理当前Entry,还会向后继续清理。

https://www.51cto.com/article/708441.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值