Java ThreadLocal 内存溢出分析及解决方法
当使用 ThreadLocal 时,每个线程都会有一个对应的 ThreadLocalMap,用来存储线程局部变量。如果线程不会被及时回收,而且每个线程都持有一个大的 ThreadLocalMap,就有可能导致内存溢出。
下面是一个可能导致内存溢出的例子:
public class ThreadLocalOOM {
private static final int THREAD_NUM = 1000;
private static final int LOOP_NUM = 100000;
private static ThreadLocal<byte[]> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUM);
for (int i = 0; i < THREAD_NUM; i++) {
executorService.execute(() -> {
threadLocal.set(new byte[1024 * 1024 * 5]); // 5 MB
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadLocal.remove();
});
}
}
}
上面的例子中,创建了 1000 个线程,每个线程都会在 ThreadLocal 中设置一个 5MB 大小的数组。然后线程会暂停 1 秒钟,最后再移除 ThreadLocal 中的值。由于每个线程都会持有一个 5MB 的数组,所以如果线程不会被及时回收,就会导致内存溢出。
为了避免这种情况,可以在使用 ThreadLocal 之后,手动调用 remove() 方法来清除线程局部变量。或者使用 InheritableThreadLocal,它会自动清除父线程中的线程局部变量。另外,合理控制线程池的大小也可以避免内存溢出问题。
原文地址: https://www.cveoy.top/t/topic/o4Ge 著作权归作者所有。请勿转载和采集!