9

我之前得出的结论是,如果您需要一个基于值(等于)的等式的 SoftReference,那么一个人的设计就很糟糕,除了一个内部人员。这是在 Google Collections 和 Guava 之后,不包括此类。但是我遇到了一个我认为可以使用这样一个对象的问题。

我们在视觉效果渲染农场中有一个资产管理系统,其中有 100 个进程在运行相同的作业,只是渲染的帧数不同。我们有一个 Oracle 数据库,需要记录所有使用的资产。在中间层资产管理系统中,我们可以使用 HashSet 来记录是否将插入 Oracle 的对象,而不是用相同的插入来冲击 Oracle。

我可以使用具有过期时间的 Google MapMaker,但我不想担心过期时间是否正确,我们的渲染可以在数小时内运行,有些则在几天内运行。使用具有等于相等性的 SoftReference 听起来是一种更好的方法,因此 JVM 将自动管理垃圾收集。

对于我想使用带有垃圾收集的 ConcurrentHashMap 解决的其他问题,我将使用 HashMap 中的强引用作为获取 equals() 相等性的关键,并将 SoftReference 作为值,以便 JVM 可以垃圾收集某些东西,但是在这个在这种情况下,值无关紧要,我没有值可以包装在 SoftReference 中以放在那里。因此,似乎使用带有 equals() 的 SoftReference 可以解决问题。

对此有何其他建议?

4

3 回答 3

1

在大多数情况下,当您想在 Google 收藏中使用软引用时,您应该调用

MapMaker.softValues()

对于强键但软值,查找将使用相等性,并且当内存紧张时,键值对将被垃圾收集。

于 2010-02-15T06:48:43.913 回答
1

由于没有ConcurrentHashSet使用软引用,因此只有两种方法:

1.) 你的方法ConcurrentHashMap

  • 覆盖equalshashCodeSoftReference
  • 在内部equals并且hashCode只能使用访问对象SoftReference#get
  • SoftReference为键,任何对象为值(只允许空)
  • 如果在访问 hashCode 或 equals 时引用过时,请将引用添加到删除队列以频繁删除已死的键。
  • 通过检查包含containsKey

2.) 使用一个ConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>>和使用hashCode作为键,以及一组同步的SoftReferences作为值。当您受到hashCode打击时,请检查所有内容SoftReferences是否相等。不是很漂亮,我同意并且很难同步。

如果我处于你的位置,我根本不会使用 SoftReferences,而是使用 ConcurrentHashMap 来保持对 POJO 的强引用。每次有新元素到达时,也将其放入 ConcurrentLinkQueue。如果队列增长超过某个限制,则开始从 HashMap 中删除元素。

于 2010-02-23T10:25:36.403 回答
0

我认为这门课将满足您的需求:

import java.util.*;
import java.lang.ref.*;

public class SoftSet<T> extends AbstractSet<T> {

  private final WeakHashMap<T,SoftReference<T>> data = new WeakHashMap<T,SoftReference<T>>();

  public boolean add(T t) {
    return null == data.put(t, new SoftReference<T>(t));
  }

  public boolean remove(Object o) {
    return null != data.remove(o);
  }

  public boolean contains(Object o) {
    return data.containsKey(o);
  }

  public Iterator<T> iterator() {
    return data.keySet().iterator();
  }

  public int size() {
    return data.size();
  }

  public void clear() {
    data.clear();
  }

  public boolean removeAll(Collection<?> c) {
    return data.keySet().removeAll(c);
  }

  public boolean retainAll(Collection<?> c) {
    return data.keySet().retainAll(c);
  }
}

这应该起作用的方式是,一旦清除了作为值的软引用,则该值仅是弱可访问的,并且可以从内部映射中删除键。

于 2010-02-17T18:28:41.453 回答