9

私は以前、値 (equals) ベースの等価性を持つ SoftReference が必要な場合、これからインターナーを除いて、設計が悪いという結論に達しました。これは、そのようなクラスを含まない Google Collections および Guava に従っています。しかし、そのようなオブジェクトを使用できると思われる問題に遭遇しました。

ビジュアル エフェクト レンダー ファームにアセット管理システムがあり、レンダリングするフレーム数だけが異なる同じジョブを実行する数百のプロセスがあります。使用されたすべての資産を記録する必要がある Oracle データベースがあります。すべてのジョブから 1 つだけが成功する同一の挿入で Oracle をドキドキする代わりに、中間層の資産管理システムでは、HashSet を使用して、オブジェクトが Oracle に挿入されるかどうかを記録できます。

有効期限付きの Google MapMaker を使用することもできますが、有効期限を正しく設定することについて心配する必要はありません。レンダリングは数時間で実行され、場合によっては数日で実行されます。等値で SoftReference を使用すると、JVM がガベージ コレクションを自動的に管理するため、はるかに優れた方法のように思えます。

ガベージ コレクションを使用して ConcurrentHashMap で解決したい他の問題については、HashMap の強い参照をキーとして使用して equals() の等価性を取得し、SoftReference を値として使用して、JVM が何かをガベージ コレクションできるようにしますが、これではその場合、値は重要ではなく、SoftReference にラップしてそこに置く値がありません。したがって、equals() で SoftReference を使用するとうまくいくようです。

これに関する他の提案はありますか?

4

3 に答える 3

1

ソフト参照を使用しないためConcurrentHashSet、2つのアプローチしかありません。

1.)あなたのアプローチConcurrentHashMap

  • オーバーライドequalshashCodeSoftReference
  • オブジェクトの内部でequalshashCodeを使用してのみオブジェクトにアクセスしますSoftReference#get
  • キーSoftReferenceとして配置し、値として任意のオブジェクトを配置します(nullのみは許可されません)
  • hashCodeまたはequalsにアクセスしているときに参照が古くなった場合は、削除キューに参照を追加して、無効になっているキーを頻繁に削除します。
  • 経由で含まれていることを確認するcontainsKey

2.)aConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>>を使用hashCodeし、キーとして使用し、値として同期されたセットを使用SoftReferencesします。hashCodeヒットしたら、すべての内容がSoftReferences等しいかどうかを確認します。あまりきれいではありませんが、同期することに同意し、注意が必要です。

私があなたの立場にある場合は、SoftReferencesをまったく使用せず、むしろConcurrentHashMapを使用してPOJOへの強力な参照を保持します。新しい要素が到着するたびに、それもConcurrentLinkQueueに入れます。キューが特定の制限を超えて大きくなった場合は、HashMapから要素の削除を開始します。

于 2010-02-23T10:25:36.403 に答える
1

ほとんどの場合、Google コレクションでソフト リファレンスを使用する場合は、

MapMaker.softValues()

強力なキーと柔軟な値を使用すると、メモリが不足している場合、ルックアップで等値が使用され、キーと値のペアがガベージ コレクションされます。

于 2010-02-15T06:48:43.913 に答える
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 に答える