前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ThreadLocal与线程池在使用中可能会出现的两个问题

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

作者头像
zhaozhen
发布2022-06-21 16:37:58
1.4K0
发布2022-06-21 16:37:58
举报

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

例如

代码语言:javascript
复制
    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

代码语言:javascript
复制
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之后的内存变化

代码语言:javascript
复制
   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 删除

本文分享自 微瞰技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 直接线程池中获取主线程或非线程池中的ThreadLocal设置的变量的值
  • 线程池中使用了ThreadLocal设置了值但是使用完后并未移除造成内存飙升或OOM
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档