gpt4 book ai didi

java - 如果线程局部映射包含对线程局部对象的弱引用,那么为什么它没有被垃圾回收?

转载 作者:搜寻专家 更新时间:2023-11-01 02:20:54 25 4
gpt4 key购买 nike

我有一个线程局部对象,它是用一个非静态内部类的对象初始化的,如下所示:

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();
}
}
}
}

我运行了这个程序,附加了 jconsole,多次触发了 GC,但内存使用率并没有下降。然后我进行了堆转储并分析了 TObject 类创建的对象数量。它表明所有 100,000 个对象都在内存中可用。

Screenshot of the heapdump, check out the object count

我将内部类设为静态,这意味着它不再强引用外部类对象并再次运行相同的代码。这里触发GC后,内存占用明显下降,内存中的对象数只有3000左右。

Screenshot of the heapdump with only 3000 objects

我不确定我理解的是:

在第一种情况下,outerObject 和 innerObject 相互持有强引用,但它们都没有被其他任何地方强引用。如果 threadlocalmap 只包含对 threadlocal 变量 (TObject) 的弱引用,并且我们没有在其他任何地方保存对外部对象 StressTestThreadLocal 的引用,为什么 threadlocal 对象不符合条件用于垃圾收集?为什么使内部类静态化会自动解决这个问题?

最佳答案

线程本地映射对实际值(在本例中为 TObject)有很强的引用。只有映射的键(ThreadLocal)是弱引用。使键成为弱引用的原因是当键不再被引用时从映射中删除条目。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/ThreadLocal.java?av=f#298

static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}

当内部类是非静态的时,对象具有对 StressTestThreadLocal 的强引用,而后者又具有对 tObjectThreadLocal(线程局部映射中的键)的强引用。因此条目永远不会被垃圾收集。

TLM -> TLM.Entry.Value (TObject) -> StressTestThreadLocal -> TLM.Entry.Key (ThreadLocal)
其中 TLM = 线程本地映射

关于java - 如果线程局部映射包含对线程局部对象的弱引用,那么为什么它没有被垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43851389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com