弱参照の使用は、これまでに実装を見たことがないため、それらのユースケースが何であり、実装がどのように機能するかを理解しようとしています。いつWeakHashMap
またはWeakReference
を使用する必要があり、どのように使用されましたか?
強い参照の問題の1つは、特に画像のような非常に大きな構造のキャッシュです。私が取り組んでいるWebサイトデザインツールのように、ユーザーが提供した画像を処理する必要があるアプリケーションがあるとします。当然、これらのイメージをキャッシュしたいのは、ディスクからイメージをロードするのは非常に高価であり、(巨大な可能性のある)イメージの2つのコピーを一度にメモリに保持する可能性を避けるためです。
画像キャッシュは、絶対に必要ではないときに画像をリロードできないようにするためのものであるため、キャッシュには常にメモリ内にある画像への参照が常に含まれていることがすぐにわかります。ただし、通常の強い参照では、その参照自体が強制的に画像をメモリに保持するため、メモリ内で画像が不要になったときを何らかの方法で判断し、キャッシュから削除して、ガベージコレクションの対象にする必要があります。ガベージコレクターの動作を複製し、オブジェクトがメモリ内にあるかどうかを手動で決定する必要があります。
nderstanding Weak References 、Ethan Nicholas
明確にするべき1つの違いは、WeakReference
とSoftReference
の違いです。
基本的に、WeakReference
は、参照されるオブジェクトにhard参照がなくなると、JVMによってGC-dになります。一方、SoftReference
dオブジェクトは、メモリを実際に再利用する必要が生じるまで、ガベージコレクターによって残される傾向があります。
valuesがWeakReference
s内に保持されているキャッシュは、ほとんど役に立たないでしょう(WeakHashMap
では、弱参照のキーです)。 SoftReferences
は、使用可能なメモリで拡大および縮小できるキャッシュを実装するときに値をラップするのに役立ちます
特にWeakReference
sおよびWeakHashMap
sの一般的な使用法の1つは、オブジェクトにプロパティを追加することです。オブジェクトにいくつかの機能やデータを追加したい場合がありますが、その場合、サブクラス化や構成はオプションではありません。その場合、追加するプロパティに拡張するオブジェクトをリンクするハッシュマップを作成することは明らかです。 。次に、プロパティが必要なときはいつでもマップで検索できます。ただし、プロパティを追加するオブジェクトが破壊されて作成される傾向がある場合、マップ内の多くの古いオブジェクトが大量のメモリを消費することになります。
代わりにWeakHashMap
を使用すると、オブジェクトはプログラムの残りの部分で使用されなくなるとすぐにマップを離れます。これは望ましい動作です。
1.4.2と1.5の間のJREの変更を回避するためにJava.awt.Component
にデータを追加するためにこれを行う必要がありました。興味のあるすべてのコンポーネント(JButton
、JFrame
、JPanel
。 ...)しかし、これははるかに少ないコードではるかに簡単でした。
WeakHashMap
およびWeakReference
のもう1つの便利なケースは、リスナーレジストリの実装です。
特定のイベントをリッスンしたいものを作成するとき、通常はリスナーを登録します。
_manager.registerListener(myListenerImpl);
_
manager
がWeakReference
でリスナーを保存する場合、それはレジスタを削除する必要がないことを意味します。 manager.removeListener(myListenerImpl)
を使用すると、リスナーまたはリスナーを保持するコンポーネントが使用できなくなると自動的に削除されるためです。
もちろん、リスナーを手動で削除することもできますbut忘れたり忘れたりした場合、メモリリークは発生せず、リスナーのガベージコレクションが妨げられません。
WeakHashMap
はどこに登場しますか?
登録されたリスナーをWeakReference
sとして保存するために使用するリスナーレジストリには、これらの参照を保存するコレクションが必要です。標準のWeakHashSet
実装はありませんJavaライブラリはWeakHashMap
のみですが、後者を簡単に使用して最初の実装の機能を「実装」できます。 :
_Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
_
このlistenerSet
を使用して新しいリスナーを登録するだけで、セットに追加するだけで、明示的に削除されなくても、リスナーが参照されなくなった場合、JVMによって自動的に削除されます。
このブログ投稿では、両方のクラスの使用方法を示しています。 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ベースのオブジェクトを提供します。要件は次のとおりです。
これは、タイプの内部ストレージマップを使用して実現されます。
WeakHashMap<Mutex, WeakReference<Mutex>>
オブジェクトはキーと値の両方です。マップの外部にオブジェクトへのハード参照がないものがある場合、ガベージコレクションできます。マップ内の値はハード参照とともに格納されるため、メモリリークを防ぐために、値をWeakReferenceでラップする必要があります。この最後の点は javadoc で説明されています。
たとえば、特定のクラスで作成されたすべてのオブジェクトを追跡する場合。これらのオブジェクトをガベージコレクションできるようにするには、オブジェクト自体ではなく、オブジェクトへの弱参照のリスト/マップを保持します。
誰かが私に幻の参照を説明できるなら、私は幸せになります...
前述のように、弱い参照は強い参照が存在する限り保持されます。
使用例としては、リスナー内でWeakReferenceを使用し、ターゲットオブジェクトへのメイン参照がなくなるとリスナーがアクティブでなくなるようにします。これは、リスナーリストからWeakReferenceが削除されることを意味するものではないことに注意してください。クリーンアップは引き続き必要ですが、たとえば、スケジュールされた時間に実行できます。これには、リッスンされたオブジェクトが強い参照を保持することを防ぎ、最終的にメモリの膨張の原因になるという効果もあります。例:ウィンドウよりも長いライフサイクルを持つモデルを参照するSwing GUIコンポーネント。
上記のようにリスナーで遊んでいると、オブジェクトがユーザーの観点から「即座に」収集されることがすぐにわかりました。
「new WeakHashMap()」のGoogleコード検索を行いました。
GNU classpathプロジェクトから多数の一致を取得し、