当前位置 : 主页 > 编程语言 > 其它开发 >

ThreadLocal与线程池共用时可能出现的的两个问题

来源:互联网 收集:自由互联 发布时间:2022-05-30
直接先线程池中获取主线程或非线程池中的ThreadLocal设置的变量的值 例如 private static final ThreadPoolExecutor syncAccessPool = new ThreadPoolExecutor( 50, 80, 8000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(6
直接先线程池中获取主线程或非线程池中的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异常

【文章转自国外服务器 http://www.558idc.com处的文章,转载请说明出处】
上一篇:MySQL、索引优化&amp;参数优化
下一篇:没有了
网友评论