ThreadLocal基本使用和内存泄漏分析

本文详细解释了Java中的线程安全问题,通过ThreadLocal解决多线程下SimpleDateFormat的内存泄露问题,并提及了Kafka在分布式系统中的作用。同时提供了面试题解析、学习笔记和实战项目源码资源。
摘要由CSDN通过智能技术生成

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

Thread t2=new Thread(new Runnable() {

@Override

public void run() {

threadLocal.set(3);

System.out.println(“t2:”+threadLocal.get());

}

});

t1.start();

t2.start();

System.out.println(threadLocal.get());

}

}

如果需要设置默认值的话,可以实现initialValue方法。

典型场景1:我们知道SimpleDateFormat的对象如果多线程使用的话会有线程不安全的问题。具体代码如下:

public class TestThreadLocal {

public static ExecutorService executorService = Executors.newFixedThreadPool(16);

private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

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

for (int i=0;i<1000;i++){

executorService.submit(new Runnable() {

@Override

public void run() {

String format = simpleDateFormat.format(new Date());

try {

Date parse = simpleDateFormat.parse(“2021-09-01 00:00:00”);

} catch (ParseException e) {

e.printStackTrace();

}

System.out.println(format);

}

});

}

Thread.sleep(3000);

executorService.shutdownNow();

}

}

运行结果如下:

可以看出,发生了异常。

方法1:我们可以改为每次都new一个新的SimpleDateFormat对象的话,这样再运行是没问题的。但是有些资源浪费。

方法2:使用ThreadLocal来解决。假设线程池里共16个线程,那我们总共16个SimpleDateFormat对象就可以应付所有的日期格式化的调用。

代码如下:

public class TestThreadLocal {

public static ExecutorService executorService = Executors.newFixedThreadPool(16);

private static ThreadLocal threadLocal=new ThreadLocal(){

@Override

protected SimpleDateFormat initialValue() {

return new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

}

};

private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

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

for (int i=0;i<1000;i++){

executorService.submit(new Runnable() {

@Override

public void run() {

String format = threadLocal.get().format(new Date());

try {

Date parse = threadLocal.get().parse(“2021-09-01 00:00:00”);

} catch (ParseException e) {

e.printStackTrace();

}

System.out.println(format);

}

});

}

Thread.sleep(3000);

executorService.shutdownNow();

}

}

注意: 如果不使用线程池,线程结束,线程里的threadLocalMap也会被回收。但是如果使用线程池,线程池里面的线程会被复用,线程里的threadLocalMap不会被回收,就造成了内存泄漏。按照正确的使用方法应该是每次用完了remove,但是这样效率就很低。还不如方法1每次去new一个新的SimpleDateFormat对象。(但个人觉得其实还好,泄漏一点也没关系,不过threadlocal毕竟不是专门解决线程安全问题的,不推荐这么用)

正确使用方法

  • 每次使用完ThreadLocal都调用它的remove()方法清除数据

  • 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。

ThreadLocal 高级部分

ThreadLocal为什么会内存泄露?

总结

大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。

麻烦帮忙转发一下这篇文章+关注我

就这一次!拼多多内部架构师培训Kafka源码笔记(现已绝版)

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。

麻烦帮忙转发一下这篇文章+关注我

[外链图片转存中…(img-P21ebRDX-1714680492419)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值