次のコードは、Collections.synchronizedMap()
を使用せずに、並行性で正確性を維持しながら書き直すことができますか?
Collections.synchronizedMap(new WeakHashMap<Class, Object>());
つまり、代わりに使用できるJava.util.concurrentの何かがありますか?単に置き換えることに注意してください
new ConcurrentHashMap<Class, Object>(new WeakHashMap<Class, Object>()));
明らかに動作しません
Guava 's CacheBuilder クラスを使用すると、これを簡単に行うことができます。
_CacheBuilder.newBuilder().weakKeys().build()
_
これにより、キーの等価セマンティクスが.equals()
ではなく_==
_に変更されることに注意してください。これは、Class
インスタンスを使用する場合は問題ではありませんが、潜在的な落とし穴です。
あるとは思わない。実際、javadocはCollections.synchronizedMap()の使用を提案しています
「ほとんどのコレクションクラスと同様に、このクラスは同期されていません。同期されたWeakHashMapは、Collections.synchronizedMapメソッドを使用して構築できます。」
Cafeine は、グアバキャッシュの人気ライバルです。
- keys automatically wrapped in weak references
- values automatically wrapped in weak or soft references
使用法:
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.weakKeys()
.weakValues()
.build(key -> createExpensiveGraph(key));
ガベージコレクターは同期マップラッパーをバイパスして、いつでも直接弱参照を変更できるため、同期マップでのWeakHashMapのラップは引き続き正しく機能しますか? WeakHashMapは、シングルスレッドモデルでのみ実際に機能すると思います。
上記のように、WeakHashMapのドキュメント https://docs.Oracle.com/javase/7/docs/api/Java/util/WeakHashMap.html には、具体的に次のように記載されています。
「同期されたWeakHashMapは、Collections.synchronizedMapメソッドを使用して構築できます」
これは、この手法がガベージコレクターの動作と連携して機能する必要があることを意味します(ドキュメントにバグがある場合を除く)。
Java 7以降を使用している場合、このユースケースはClassValue
https://docs.Oracle.com/)を使用してスレッドセーフな方法で解決されます。 javase/7/docs/api/Java/lang/ClassValue.htmlremove
の使用が必要な場合は、並行性について慎重に検討し、ドキュメントをよく読んでください。
Java 6以下を使用している場合。いいえ、WeakHashMapを同期する必要があります。