LoopとBrunoCondeはそれをほぼカバーしていますが、私がそのコードを書いたので...
設計の目標は、ユーザーがリリースメカニズムを呼び出さないようにすることでした。つまり、ユーザーがミューテックスを参照しなくなったときに、そのミューテックスはガベージコレクションの対象になります。
なぜMutexインスタンスの周りにWeakReferenceをラップする必要があるのですか?
マップはWeakHashMapです:
private final Map mutexMap = new WeakHashMap();
このマップは、ミューテックスへの参照を保持するために使用されますが、キーと値に同じオブジェクトを使用する場合、そのオブジェクトはガベージコレクションの対象にはなりません。Javadoc:
実装上の注意:WeakHashMapの値オブジェクトは、通常の強力な参照によって保持されます。したがって、値オブジェクトが直接または間接的に自身のキーを強く参照しないように注意する必要があります。これにより、キーが破棄されるのを防ぐことができます。値オブジェクトは、WeakHashMap自体を介してそのキーを間接的に参照する場合があることに注意してください。つまり、値オブジェクトは、関連する値オブジェクトが最初の値オブジェクトのキーを強く参照する他のキーオブジェクトを強く参照する場合があります。これに対処する1つの方法は、m.put(key、new WeakReference(value))のように、挿入する前に値自体をWeakReferences内でラップし、各getでアンラップすることです。
文字列->ミューテックスからマップを作成する方が良いのではないですか?
その文字列値はいつガベージコレクションされますか?毎回同じ参照が渡されていますか?intern()が呼び出されましたか?インターンに電話した場合、ストリングはどのくらいの期間存続しますか?文字列がキーである場合、そのミューテックスへの参照を保持する必要がなくなった後、ミューテックスはガベージコレクションの対象とならない可能性があります。
putを2回呼び出す必要があるのはなぜですか?
メソッドがマップ内のミューテックスへの強力な参照を取得できるようになるまで、処理する2つのケースがあります。
- WeakReferenceはガベージコレクションされています(またはそもそもそこにありませんでした)
- WeakReferenceの内容は、参照が取得された後に収集されたガベージです。
putは一度だけ呼び出されます。メソッドは直後に戻ります。
(WeakReferenceは2番目の場所で再利用できますが、大幅な改善になるとは思いません。)
もちろん、誰かがコードに誤りを見つけた場合は、私に知らせてください。喜んで修正します。また、単体テストは実装がリークしていないことを確認しようとするため、コードを自由に変更して、テストを実行するとどうなるかを確認してください。