java threadlocal 缺点_ThreadLocalMap 如果使用强引用,发生了内存泄漏,会发生什么?...

之前mark了一下忘记回复了233

因为之前跟原来项目经理聊天的时候有聊到过这个场景,特意来回复一下

针对ThreadLocal没有手动remove的情况可能会出现的问题

如果是单纯的单例情况下 确实不会有问题,因为每次启动完了spring自己就回收了,但是如果在线程池的调用情况下 就会有问题,因为线程池中的线程是固定维护的,如果你手动set了以后没有及时remove,可能导致后续的任务获取到前一个副本的值,比如这个demo

public class SchedulePoolTest {

public static void main(String[] args) throws Exception {

ThreadPoolExecutor executorService = new ThreadPoolExecutor(1,5,2L,TimeUnit.SECONDS,new LinkedBlockingQueue<>(2),new TestThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());

class Task implements Runnable{

private String key;

public Task(String key) {

this.key = key;

}

@Override

public void run() {

ThreadLocalContext threadLocalContext = new ThreadLocalContext();

Map map = new HashMap<>();

map.put(key,key);

if (null != ThreadLocalTest.get()){

}else {

threadLocalContext.setMap(map);

ThreadLocalTest.setThreadLocal(threadLocalContext);

}

System.out.println(Thread.currentThread().getName()+"-----"+ JSON.toJSONString(ThreadLocalTest.get()));

// ThreadLocalTest.remove(); }

}

int i=0;

while(true){

executorService.submit(new Task(String.valueOf(i++)));

}

}

}

这个测试线程池,我开起了5个总线程,然后注释了remove,本来逻辑应该是无线递增i的打印输出,但是实际打印的结果是

什么妖魔鬼怪都有,因为本身没有做清除,而线程在执行完成后会返回给池里而不是销毁,所以导致后续的任务都读到了原来的线程,导致threadlocal储存数据异常,而手动remove之后就不会有这个问题

另外针对内存溢出来说,因为ThreadLocal本身其实是ThreadLocalMap的,可以想一下,如果是强引用,那么不管做不做remove,在GC的时候,由于本身是持有了一个映射到对象的key,就一直不会回收,从而导致内存溢出

如果是弱引用,那么在remove后,持有的key指向的对象不存在了,gc时就会自动被回收了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值