27

SoftReferenceインスタンス変数として作成された場合にWeakReferenceのみ役立ちますか?メソッドスコープでそれらを使用することに何か利点はありますか?

他の大きな部分はReferenceQueueです。どの参照がガベージと判断されたかを追跡できることに加えてReference.enqueue()、ガベージコレクションのオブジェクトを強制的に登録するために使用できますか?

たとえば、オブジェクト内の(強力な参照によって保持されている)重いメモリリソースを使用するメソッドを作成し、それらをキューに入れるための参照を作成することは価値がありますか?

Object bigObject;
public void dispose() {
    ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
    WeakReference<Object> ref = new WeakReference<Object>(bigObject, queue);
    bigObject = null;
    ref.enqueue();
}

(この場合のObjectは、大量のメモリを使用するオブジェクトタイプを表していると想像してください...などBufferedImage

これは現実的な効果がありますか?それとも、これは単なるコードの無駄ですか?

4

4 に答える 4

36

参照キューの一般的なイディオムの1つは、たとえば、サブクラスを使用WeakReferenceしてクリーンアップに必要な情報を添付し、次にポーリングしReferenceQueueてクリーンアップタスクを取得することです。

ReferenceQueue<Foo> fooQueue = new ReferenceQueue<Foo>();

class ReferenceWithCleanup extends WeakReference<Foo> {
  Bar bar;
  ReferenceWithCleanup(Foo foo, Bar bar) {
    super(foo, fooQueue);
    this.bar = bar;
  }
  public void cleanUp() {
    bar.cleanUp();
  }
}

public Thread cleanupThread = new Thread() {
  public void run() {
    while(true) {
      ReferenceWithCleanup ref = (ReferenceWithCleanup)fooQueue.remove();
      ref.cleanUp();
    }
  }
}

public void doStuff() {
  cleanupThread.start();
  Foo foo = new Foo();
  Bar bar = new Bar();
  ReferenceWithCleanup ref = new ReferenceWithCleanup(foo, bar);
  ... // From now on, once you release all non-weak references to foo,
      // then at some indeterminate point in the future, bar.cleanUp() will
      // be run. You can force it by calling ref.enqueue().
}

たとえば、が選択さCacheBuilderれた場合のGuavaの実装の内部は、このアプローチを使用します。weakKeys

于 2013-01-22T02:38:49.473 に答える
7

オブジェクトがそのオブジェクトに対してWeakReferencesしかない(または参照がまったくない!)場合、Javaがメモリ内により多くのスペースを確保する必要があるときはいつでも、ガベージコレクションを行うことができます。したがって、WeakReferenceオブジェクトをメモリに残したいときはいつでもsを使用しますが、オブジェクトをそれほどひどく残す必要はありません(たとえば、Javaがオブジェクトをガベージコレクションする必要がある場合は、問題ありません。なんとかして、その間に元に戻すことができます。 Javaの方がパフォーマンスが優れています)

aをエンキューするWeakReferenceと、を繰り返して、ReferenceQueueガベージコレクションされた参照と収集されていない参照を判別できます。それがすべてです-あなたがこれを知る必要がある場合にのみそれをしてください。

続きを読む: http ://weblogs.java.net/blog/2006/05/04/understanding-weak-references

于 2013-01-22T02:24:32.473 に答える
5

一般的に行うことの1つは、ソフト参照のマップを作成することです。

Map<String, SoftReference<BigThing>> cache = new HashMap<>();
Set<String> thingsIAmCurrentlyGetting = new HashSet<String>();
Object mutex = new Object();

BigThing getThing(String key) {
  synchronized(mutex) {
    while(thingsIAmCurrentlyGetting.contains(key)) {
      mutex.wait();
    }
    SoftReference<BigThing> ref = cache.get(key);
    BigThing bigThing = ref == null ? null : ref.get();
    if(bigThing != null) return bigThing;
    thingsIAmCurrentlyGetting.add(key);
  }

  BigThing bigThing = getBigThing(key); // this may take a while to run.

  synchronized(mutex) {
    cache.put(key, bigThing);
    thingsIAmCurrentlyGetting.remove(key);
    mutex.notifyAll();
  }

  return bigThing;
}

私はここに私の古い学校を示しています-新しいJavaパッケージにはおそらくこれを行うためのはるかに優れた方法があります。

于 2014-04-26T13:43:24.363 に答える
1

ここでの質問はわかりませんが、次のようになります。

1)soft refは、jvmが実際にメモリを必要とするまで参照を保持しようとします。キャッシュ、特にLRUキャッシュに最適です。グアバの多くの例を見てください。

2)弱いrefは、gcがオブジェクトを解放するのをまったく妨げようとしないでください。そのオブジェクトがまだどこかで使用されているかどうかを知りたい場合に使用されます。たとえば、スレッドとクラスに関する情報を格納するために使用されるため、スレッドまたはクラスが使用されなくなったときに、それに関連するメタ情報を破棄できます。

3)ファントム参照は弱いようですが、実際のオブジェクトを参照することはできません。このようにして、ファントムを回しても実際のオブジェクトを再開できないことを確認できます(これは参照が弱い場合のリスクです)。また、ファントムrefは、refをクリアするまで、収集されるオブジェクトをブロックしています。

ReferenceQueue:そこに何かを入れないでください。gcがあなたに代わって行います。それらを1つずつチェックしなくても、いくつかの参照がいつリリースされるかを知ることができます。

于 2017-08-25T10:23:38.797 に答える