6

簡単な背景 私は、かなり頻繁に変更されるいくつかの値をキャッシュするために使用した同時実行マップを持っています (まだテストからキャッシュする価値があります)。値の有効期限を調べて、定期的にキャッシュからアイテムを削除したいと考えています。keySet() メソッドを使用してすべてのキーへの参照を取得し、値を確認して、期限切れの場合はそれらを削除します。他のスレッドでは、キャッシュは常に照会および更新 (削除) されています。

keySet() の javadocs から、キーセット Set を繰り返し処理しているときにマップが変更された場合、結果が未定義であることが言及されています。明らかに、結果が有効になるように、これを処理する定義された方法が必要です。Set を HashSet に渡してから、このセットを反復処理するだけで十分でしょうか?このセットはマップによってサポートされないことがわかっているため、これはメモリの無駄な方法ですか? どんなアイデアでも大歓迎です。

残念ながら、私の evictor はアイテムを並行マップから削除する唯一の方法ではないので、反復する前に keySet を別の Set にコピーする必要があると言って間違いありません。

前もって感謝します

編集: ConcurrentMap keySet() の代わりに Map keySet() メソッドの javadoc を読んでいたことがわかりました。ありがとうございます

このマップに含まれるキーのセット ビューを返します。セットはマップに支えられているため、マップへの変更はセットに反映され、その逆も同様です。セットに対する反復の進行中にマップが変更された場合 (反復子自体の削除操作を除く)、反復の結果は未定義です。このセットは、Iterator.remove、Set.remove、removeAll、retainAll、および clear オペレーションを介して、対応するマッピングをマップから削除する要素の削除をサポートしています。add または addAll 操作はサポートされていません。

4

2 に答える 2

6

Java Concurrent HashMapを使用していますか? keySet() のドキュメントから、便利な方法で動作するように見えます。

このマップに含まれるキーのセット ビューを返します。セットはマップに支えられているため、マップへの変更はセットに反映され、その逆も同様です。セットは、Iterator.remove、Set.remove、removeAll、retainAll、および clear オペレーションを介して、このマップから対応するマッピングを削除する要素の削除をサポートします。add または addAll 操作はサポートされていません。ビューの返されたイテレータは、ConcurrentModificationException を決してスローしない「弱い一貫性のある」イテレータであり、イテレータの構築時に存在していた要素をトラバースすることを保証し、構築後の変更を反映する可能性があります (ただし保証はされません)。

つまり、ものを削除でき、問題ないはずです。

この実装を使用していない場合は、どちらを使用していますか (そしてその理由は? 冗談ではありませんが、なぜその選択をしたのかを知ることは興味深いでしょう)

于 2009-03-27T12:08:51.197 に答える
0

LRU キャッシュで問題が解決しない場合は、 LinkedHashMapを確認してください。これにより、LRU キャッシュの実装が簡単になり、 Collections.synchronizedMapへの呼び出しで結果をラップすることで、結果をスレッドセーフにすることができます。

于 2009-03-27T12:08:36.847 に答える