写点什么

ThreadLocal 基本使用和内存泄漏分析,kafka 性能调优

作者:Java高工P7
  • 2021 年 11 月 10 日
  • 本文字数:1345 字

    阅读完需:约 4 分钟

// }


// };


public static void main(String[] args) {


Thread t1=new Thread(new Runnable() {


@Override


public void run() {


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


}


});


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<SimpleDateFormat> threadLocal=new ThreadLocal<SimpleDateFormat>(){


@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 {


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


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 毕竟不是专门解决线程安全问题的,不推荐这么用)

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
ThreadLocal基本使用和内存泄漏分析,kafka性能调优