首先ThreadLocal之所以会出现内存泄漏主要原因是value没有被gc回收(可以手动remove)。
ThreadLocal的key与value是弱引用,但是value与thread之间是强引用,所以线程如果被回收是不会出现内存泄漏的。但是如果采用的线程池,线程有可能一直存在,这样就会导致内存泄漏。
线程池里的线程,核心线程正常执行的话,是不会被回收且一直存在的,除非出现异常,线程池会重新创建新线程。
public class ThreadPoolDemo {
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,2,5000, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(1));
public static void main(String[] args) throws InterruptedException {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getId());
int i = 1/0;
});
Thread.sleep(6000);
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getId());
});
threadPoolExecutor.shutdown();
}
}
输出
12
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at co.tzp.java.async.ThreadPoolDemo.lambda$main$0(ThreadPoolDemo.java:19)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
13
Process finished with exit code 0
最大线程被创建后,出现异常或者达到存活的最大时间,线程也会被销毁。
public class ThreadPoolDemo {
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0,2,5000, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(1));
public static void main(String[] args) throws InterruptedException {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getId());
});
Thread.sleep(6000);
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getId());
});
threadPoolExecutor.shutdown();
}
}
输出:
12
13
Process finished with exit code 0