I have a threadlocal object that is initialized with a non-stationary inner class object, for example:
public class StressTestThreadLocal {
private final ThreadLocal<TObject> tObjectThreadLocal = ThreadLocal.withInitial(
() -> new TObject(1000));
private static ExecutorService executorService = Executors.newFixedThreadPool(4);
private void startThread() {
executorService.submit(tObjectThreadLocal::get);
}
public class TObject {
List<Integer> test;
TObject(int n) {
test = new ArrayList<>();
for (int i = 0; i < n; i++) {
test.add(i);
}
System.out.println("Done making TObject " + UUID.randomUUID());
}
}
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
StressTestThreadLocal testThreadLocal = new StressTestThreadLocal();
testThreadLocal.startThread();
}
while (true) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I ran this program, attached jconsole, launched GC several times, but memory usage did not decrease. Then I took heapdump and analyzed the number of objects created in the class TObject. He showed that all 100,000 objects are available in memory.
Screenshot with heapdump, check the number of objects
I made the static meaning of the inner class that it no longer refers to the external object of the class and runs the same code again. Here, the launch of the GC significantly reduced memory usage, and the number of objects in memory was only about 3,000.
heapdump 3000
, :
, . threadlocalmap threadlocal (TObject), StressTestThreadLocal - , threadlocal ? static ?