直接先线程池中获取主线程或非线程池中的ThreadLocal设置的变量的值 例如 private static final ThreadPoolExecutor syncAccessPool = new ThreadPoolExecutor( 50, 80, 8000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(6
例如
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中获取到方法中,再设置到线程池
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处的文章,转载请说明出处】