专栏首页用户1096981的专栏ThreadLocal与线程池在使用中可能会出现的两个问题

ThreadLocal与线程池在使用中可能会出现的两个问题

直接线程池中获取主线程或非线程池中的ThreadLocal设置的变量的值

例如

    private static final ThreadPoolExecutor syncAccessPool = new ThreadPoolExecutor(
            50,
            80,
            8000,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(600)
    );
    public static void main(String[] args) {
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        threadLocal.set("userId115807");
        syncAccessPool.execute(()->{
            System.out.println(threadLocal.get());
        });
    }

最后打印的结果是null

解决办法:真实使用中相信大家不会这么使用的,但是我出错主要是因为使用了封装的方法,封装的方法中使用了ThreadLocal,这种情况下要先从ThreadLocal中获取到方法中,再设置到线程池

线程池中使用了ThreadLocal设置了值但是使用完后并未移除造成内存飙升或OOM

public class ThreadLocalOOM {
    static class LocalVariable{
        private Long[] a = new Long[1024*1024];
    }
    private static final ThreadPoolExecutor syncAccessPool = new ThreadPoolExecutor(
            50,
            80,
            8000,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(600)
    );
    final static  ThreadLocal<LocalVariable> threadLocal = new ThreadLocal<LocalVariable>();


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

        Thread.sleep(10000);
        for (int i=0;i<100;i++){
            syncAccessPool.execute(()->{
                threadLocal.set(new LocalVariable());
                System.out.println("use local variable");
            });
            Thread.sleep(1000);
        }
        System.out.println("pool execute over");
    }
}

这个程序使用jconsole程序观察到的内存变化为

在使用完之后remove之后的内存变化

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

        for (int i=0;i<100;i++){
            syncAccessPool.execute(()->{
                threadLocal.set(new LocalVariable());
                System.out.println("use local variable");
                threadLocal.remove();
            });
            Thread.sleep(1000);
        }
        System.out.println("pool execute over");
    }

内存相比之前降低了几倍。这个原因就是没有remove,线程池中所有存在的线程都会持有这个本地变量,导致内存暴涨。如果将private Long[] a = new Long[1024*1024]; 扩大可能就会很快抛出OOM异常

文章分享自微信公众号:
微瞰技术

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!

作者:赵镇
原始发表时间:2022-05-01
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • Hystrix 如何解决 ThreadLocal 信息丢失

    笔者在业务开发中涉及到使用 ThreadLocal 来存放上下文链路中一些关键信息,其中一些业务实现对外部接口依赖,对这些依赖接口使用了Hystrix作熔断保护...

    2020labs小助手
  • 阿里Java编程规约【七】 并发处理

    1. 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 说明:资源驱动类、工具类、单例工厂类都需要注意。

    acc8226
  • BAT大厂面试必问专题之Java多线程

      根据众多面试的同学反馈的面试题,给大家整理一版最新的面试专题,希望对大家有所帮助。

    用户4919348
  • 线程池与Threadlocal

    线程池是为了使线程能够得到循环的利用,线程池里面养着一些线程,有任务需要使用线程的时候就往线程池里抓线程对象出来使用。线程池里的线程能够重复使用,所以在资源上能...

    端碗吹水
  • Java多线程编程-(10)-看了这篇关于ThreadLocal的原理应该透彻了

    ThreadLocal可以说是笔试面试的常客,每逢面试基本都会问到,关于ThreadLocal的原理以及不正当的使用造成的OOM内存溢出的问题,值得花时间仔细研...

    Java后端技术
  • Java并发之ThreadLocal

    首先说明,ThreadLocal与线程同步无关。ThreadLocal虽然提供了一种解决多线程环境下成员变量的问题,但是它并不是解决多线程共享变量的问题。

    趣学程序-shaofeer
  • Java开发手册-并发处理

    自定义线程工厂,并且根据外部特征进行分组,比如,来自同一机房的调用,把机房编号赋值给

    Vincent-yuan
  • 程序员必知的并发编程注意事项

    获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 单例对象会被多线程共享,因此要保证它是线程安全的,它其中的方法都要保证是线程安全的。 工具类、资源...

    大闲人柴毛毛
  • 面渣逆袭:Java并发六十问,快来看看你会多少道!

    大家好,我是老三,面渣逆袭 继续,这节我们来盘一盘另一个面试必问知识点——Java并发。

    三分恶
  • java并发系列 - 第28天:实战篇,微服务日志的伤痛,一并帮你解决掉

    先介绍一下多数公司采用的方式:目前比较流行的是采用springcloud(或者dubbo)做微服务,按照业拆分为多个独立的服务,服务采用集群的方式部署在不同的机...

    路人甲Java
  • 调用链系列四:调用链上下文传递

    在之前的调用链系列文章中,我们已经对调用链进行了详细介绍,相信大家已经对调用链技术有了基本的了解。

    宜信技术学院
  • ThreadLocal与Java引用类型(文末含福利)

    今天以 “TheadLocal 为什么会导致内存泄漏” 为题与朋友们讨论了一波,引出了一些原理性的内容,本文就这个问题作答,并扩展相关的知识点

    Android扫地僧
  • 不堆概念、换个角度聊多线程并发编程

    在上一篇文档《JAVA基于CompletableFuture的流水线并行处理深度实践,满满干货》中,我们一起探讨了JAVA中并行编码的相关内容,在文中也一起比较...

    架构悟道
  • 每日一博 - ThreadLocal VS InheritableThreadLocal VS TransmittableThreadLocal

    多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才...

    小小工匠
  • 线程池-Threadlocal

    ThreadLoclc初衷是线程并发时,解决变量共享问题,但是由于过度设计,比如弱引用的和哈希碰撞,导致理解难度大、使用成本高,反而成为故障高发点,容易出现内存...

    DougWang
  • 多线程知识回顾

    以前看过不少JDK源码,最近回顾了一下笔记,所以在这里对几个很常见到的线程类做个记录。

    Java编程指南
  • 使用 ThreadLocal 如何避免内存泄漏?

    每个线程需要一个独享对象(通常是工具类,典型需要使用的类有SimpleDateFormat和Random)

    Java识堂
  • Java面试考点3之并发与多线程

    线程是 JVM 执行任务的最小单元,理解线程的状态转换是理解后续多线程问题的基础。在 JVM 运行中,线程一共有 NEW、RUNNABLE、BLOCKED、WA...

    马拉松程序员
  • TransmittableThreadLocal在使用线程池等会缓存线程的组件情况下传递ThreadLocal

    TransmittableThreadLocal 是Alibaba开源的、用于解决 “在使用线程池等会缓存线程的组件情况下传递ThreadLocal” 问题的 ...

    chinotan

扫码关注腾讯云开发者

领取腾讯云代金券