【问题标题】:Java: Stack with weak referencesJava:弱引用堆栈
【发布时间】:2012-08-10 21:49:44
【问题描述】:

在 Java 中有一种称为 WeakHashMap 的数据结构,它将弱引用存储为键。每当弱引用从内存中取出时,条目就会从映射中删除。

如果我有一个 Stack 或 Set 等数据结构来存储弱引用,当弱引用从内存中取出时,它们的条目是否会自动删除?

下面是一个存储弱引用的堆栈示例。

Stack<WeakReference<Object>> objStack = new Stack<WeakReference<Object>>();

【问题讨论】:

  • 你确定它不会返回空值吗?
  • 如果您想在实际应用程序中使用弱引用,请不要这样做!构建核心库的人后悔添加它们,因为它们没有提供任何好处。如果您有兴趣,请观看presentation
  • 感谢视频链接,但我认为有些项目可以很好地利用 Wea​​kReferences。例如,查看适用于 Android 的 Robotium 项目code.google.com/p/robotium
  • 嗯,我很确定我对 SoftReferences 感到困惑。感谢项目的链接,我去看看。

标签: java stack set weak-references weakhashmap


【解决方案1】:

是的。您所描述的是一般的弱引用属性,而不是具体的WeakHashMap

来自the API

假设垃圾收集器在某个时间点确定一个对象是弱可达的。那时它会自动清除对该对象的所有弱引用...

【讨论】:

  • 那么如果你有一个 WeakReferences 的 LinkedList 并且列表中间的一个 WeakReferences 内存不足,你的 LinkedList 会按预期工作吗?
  • 我不知道如何回答...这取决于您认为“符合预期”。
  • 我想我不明白的是,当您在 WeakReference 上调用 .get() 时,它会获取实际对象。 WeakReference 永远不会仅将其指向的对象设置为 null。
  • 啊,明白了。好了,现在你知道了!
  • @zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz 是的,没错(大约get())。如果您想摆脱现在的“空”WeakReference,您需要手动执行此操作。如果您查看WeakHashMap 的代码,您会发现他们就是这样做的。
【解决方案2】:

迟到总比没有好。

这不是弱引用的工作方式。 WeakReference-object 将始终存在,但它的 get()-method 可能会返回原始对象或 null(如果原始对象是 GC:ed)。

这意味着您的 Stack 将始终包含一个 WeakReference-object。

这是我做的一个详细测试(但是它取决于 JVM 在中间执行 GC,这可能会或可能不会发生在“命令”上 - 如果没有发生,请尝试添加更多 System.gc():s) :

public static void main(String[] args) {
    // Set up
    Object object = new Object();
    final WeakReference<Object> weakReference = new WeakReference<>(object);
    final Stack<WeakReference<Object>> references = new Stack<>();      
    references.add(weakReference);

    // Before
    System.out.println("Before:");

    references.forEach(r -> {
        System.out.println("Reference: " + r);
        System.out.println("Object: " + r.get());
    });

    // GC
    object = null;

    System.gc();
    System.gc();
    System.gc();

    // After
    System.out.println("After:");
    references.forEach(r -> {
        System.out.println("Reference: " + r);
        System.out.println("Object: " + r.get());
    });
}

输出:

Before:
Reference: java.lang.ref.WeakReference@238e0d81
Object: java.lang.Object@31221be2
After:
Reference: java.lang.ref.WeakReference@238e0d81
Object: null

您最好的方法可能是在“弹出”它们后忽略 get() 返回 null 的条目。

旁注:我的第一个测试是使用一个字符串对象,它从未得到 GC:ed。这是因为 Java 中的字符串是“interned”(参见String.intern()),这意味着有一个隐藏的静态字符串缓存可以重用。字符串永远不会被 GC:ed,除非字符串池已满(或类似的东西......)我认为字符串是唯一具有这种“特殊”特性的 Java 对象,但我建议始终使用定制对象在 WeakReference 中确保它得到正确的 GC:ed。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 2011-03-27
    • 2021-11-20
    • 2012-10-16
    • 2012-02-06
    • 1970-01-01
    • 2018-06-21
    相关资源
    最近更新 更多