web-dev-qa-db-ja.com

WeakHashMapまたはWeakReferenceはいつ使用しますか?

弱参照の使用は、これまでに実装を見たことがないため、それらのユースケースが何であり、実装がどのように機能するかを理解しようとしています。いつWeakHashMapまたはWeakReferenceを使用する必要があり、どのように使用されましたか?

161
18Rabbit

強い参照の問題の1つは、特に画像のような非常に大きな構造のキャッシュです。私が取り組んでいるWebサイトデザインツールのように、ユーザーが提供した画像を処理する必要があるアプリケーションがあるとします。当然、これらのイメージをキャッシュしたいのは、ディスクからイメージをロードするのは非常に高価であり、(巨大な可能性のある)イメージの2つのコピーを一度にメモリに保持する可能性を避けるためです。

画像キャッシュは、絶対に必要ではないときに画像をリロードできないようにするためのものであるため、キャッシュには常にメモリ内にある画像への参照が常に含まれていることがすぐにわかります。ただし、通常の強い参照では、その参照自体が強制的に画像をメモリに保持するため、メモリ内で画像が不要になったときを何らかの方法で判断し、キャッシュから削除して、ガベージコレクションの対象にする必要があります。ガベージコレクターの動作を複製し、オブジェクトがメモリ内にあるかどうかを手動で決定する必要があります。

nderstanding Weak References 、Ethan Nicholas

96
Jacob Krall

明確にするべき1つの違いは、WeakReferenceSoftReferenceの違いです。

基本的に、WeakReferenceは、参照されるオブジェクトにhard参照がなくなると、JVMによってGC-dになります。一方、SoftReferencedオブジェクトは、メモリを実際に再利用する必要が生じるまで、ガベージコレクターによって残される傾向があります。

valuesWeakReferences内に保持されているキャッシュは、ほとんど役に立たないでしょう(WeakHashMapでは、弱参照のキーです)。 SoftReferencesは、使用可能なメモリで拡大および縮小できるキャッシュを実装するときに値をラップするのに役立ちます

52
oxbow_lakes

特にWeakReferencesおよびWeakHashMapsの一般的な使用法の1つは、オブジェクトにプロパティを追加することです。オブジェクトにいくつかの機能やデータを追加したい場合がありますが、その場合、サブクラス化や構成はオプションではありません。その場合、追加するプロパティに拡張するオブジェクトをリンクするハッシュマップを作成することは明らかです。 。次に、プロパティが必要なときはいつでもマップで検索できます。ただし、プロパティを追加するオブジェクトが破壊されて作成される傾向がある場合、マップ内の多くの古いオブジェクトが大量のメモリを消費することになります。

代わりにWeakHashMapを使用すると、オブジェクトはプログラムの残りの部分で使用されなくなるとすぐにマップを離れます。これは望ましい動作です。

1.4.2と1.5の間のJREの変更を回避するためにJava.awt.Componentにデータを追加するためにこれを行う必要がありました。興味のあるすべてのコンポーネント(JButtonJFrameJPanel。 ...)しかし、これははるかに少ないコードではるかに簡単でした。

30
luke

WeakHashMapおよびWeakReferenceのもう1つの便利なケースは、リスナーレジストリの実装です。

特定のイベントをリッスンしたいものを作成するとき、通常はリスナーを登録します。

_manager.registerListener(myListenerImpl);
_

managerWeakReferenceでリスナーを保存する場合、それはレジスタを削除する必要がないことを意味します。 manager.removeListener(myListenerImpl)を使用すると、リスナーまたはリスナーを保持するコンポーネントが使用できなくなると自動的に削除されるためです。

もちろん、リスナーを手動で削除することもできますbut忘れたり忘れたりした場合、メモリリークは発生せず、リスナーのガベージコレクションが妨げられません。

WeakHashMapはどこに登場しますか?

登録されたリスナーをWeakReferencesとして保存するために使用するリスナーレジストリには、これらの参照を保存するコレクションが必要です。標準のWeakHashSet実装はありませんJavaライブラリはWeakHashMapのみですが、後者を簡単に使用して最初の実装の機能を「実装」できます。 :

_Set<ListenerType> listenerSet =
    Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
_

このlistenerSetを使用して新しいリスナーを登録するだけで、セットに追加するだけで、明示的に削除されなくても、リスナーが参照されなくなった場合、JVMによって自動的に削除されます。

20
icza

このブログ投稿では、両方のクラスの使用方法を示しています。 Java:IDで同期 。使用方法は次のようになります。

private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();

public void performTask(String resourceId) {
    IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
    synchronized (mutext) {
        // look up the resource and do something with it
    }
}

IdMutextProviderは、同期するIDベースのオブジェクトを提供します。要件は次のとおりです。

  • 同等のIDを同時に使用するには、同じオブジェクトへの参照を返す必要があります
  • 異なるIDに対して異なるオブジェクトを返す必要があります
  • リリースメカニズムなし(オブジェクトはプロバイダーに返されません)
  • リークしてはなりません(未使用のオブジェクトはガベージコレクションの対象です)

これは、タイプの内部ストレージマップを使用して実現されます。

WeakHashMap<Mutex, WeakReference<Mutex>>

オブジェクトはキーと値の両方です。マップの外部にオブジェクトへのハード参照がないものがある場合、ガベージコレクションできます。マップ内の値はハード参照とともに格納されるため、メモリリークを防ぐために、値をWeakReferenceでラップする必要があります。この最後の点は javadoc で説明されています。

4
McDowell

たとえば、特定のクラスで作成されたすべてのオブジェクトを追跡する場合。これらのオブジェクトをガベージコレクションできるようにするには、オブジェクト自体ではなく、オブジェクトへの弱参照のリスト/マップを保持します。

誰かが私に幻の参照を説明できるなら、私は幸せになります...

3
JesperE

前述のように、弱い参照は強い参照が存在する限り保持されます。

使用例としては、リスナー内でWeakReferenceを使用し、ターゲットオブジェクトへのメイン参照がなくなるとリスナーがアクティブでなくなるようにします。これは、リスナーリストからWeakReferenceが削除されることを意味するものではないことに注意してください。クリーンアップは引き続き必要ですが、たとえば、スケジュールされた時間に実行できます。これには、リッスンされたオブジェクトが強い参照を保持することを防ぎ、最終的にメモリの膨張の原因になるという効果もあります。例:ウィンドウよりも長いライフサイクルを持つモデルを参照するSwing GUIコンポーネント。

上記のようにリスナーで遊んでいると、オブジェクトがユーザーの観点から「即座に」収集されることがすぐにわかりました。

3
Louis Jacomet

「new WeakHashMap()」のGoogleコード検索を行いました。

GNU classpathプロジェクトから多数の一致を取得し、

  1. Apache xbeanプロジェクト: WeakHashMapEditor.Java
  2. Apache Luceneプロジェクト: CachingWrapperFilter.Java
1
anjanb