質問

LinkedHashMapaccessOrder trueとともに使用し、データのLRUキャッシュとして常に最大500エントリを許可しました。しかし、スケーラビリティの問題のため、スレッドセーフな代替手段に移りたいと思います。 ConcurrentHashMapはその点では良いように見えますが、removeEldestEntry(Map.Entry e)にある<=>および<=>の機能が欠けています。誰かがリンクを指すか、実装を簡単にするのを手伝ってくれますか?

役に立ちましたか?

解決

最近、ConcurrentHashMap<String,CacheEntry>で同様のことを行いました。CacheEntryは実際のアイテムをラップし、キャッシュエビクションの統計を追加します。有効期限、挿入時間(FIFO / LIFOエビクションの場合)、最終使用時間(LRU / MRUエビクションの場合)、数値ヒットの数(LFU / MFUエビクションの場合)など。実際のエビクションは同期され、ArrayList<CacheEntry>を作成し、エビクション戦略に適切なコンパレータを使用して、その上でCollections.sort()を実行します。これは費用がかかるため、各エビクションはCacheEntriesの下位5%を落とします。パフォーマンスチューニングが役立つと確信しています。

FIFOを使用しているため、別の ConcurrentLinkedQueue 。オブジェクトをConcurrentHashMapに追加するときは、そのオブジェクトのConcurrentLinkedQueue.add()を実行します。エントリを削除する場合は、ConcurrentLinkedQueue.poll()を実行して最も古いオブジェクトを削除してから、ConcurrentHashMapからも削除します。

更新:この領域の他の可能性には、Javaコレクション同期が含まれます。ラッパーおよびJava 1.6 ConcurrentSkipListMap

他のヒント

ehcacheのような多くのキャッシングソリューションの1つを使用してみましたか? LinkedHashMapをReadWriteLockで使用してみてください。これにより、同時読み取りアクセスが可能になります。

これは今では古いように見えるかもしれませんが、少なくとも自分の履歴追跡のために、ここにソリューションを追加します:WeakReference、ConcurrentLinkedQueue、およびインターフェイスのK-<!> gt;サブクラスをマッピングするConcurrentHashMapこれは、Kに基づいて値オブジェクトの逆シリアル化を定義して、LRUキャッシングを正しく実行します。キューは強い参照を保持し、GCは適切なときにメモリから値を追い出します。キューのサイズを追跡するにはAtomicIntegerが関係します。実際にキューを検査して、排除するタイミングを決定することはできません。キャッシュは、キューへのエビクションとキューへの追加、およびマップ管理を処理します。 GCがメモリから値を追い出した場合、逆シリアル化インターフェイスの実装は値の取得を処理します。また、ディスクへのスプール/スプールされたものの再読み取りを伴う別の実装もありましたが、スプール/読み取りを同期する必要があったため、ここに投稿したソリューションよりもかなり低速でした。

<!> quot; thread-safe <!> quot;でスケーラビリティの問題を解決したいということです。代替。 <!> quot;スレッドセーフティ<!> quot;ここでは、外部同期なしの同時使用による破損を被らないという点で、構造は同時アクセスの試行に対して耐性であることを意味します。ただし、このような許容値は、必ずしも<!> quot;スケーラビリティ<!> quot;の改善に役立つとは限りません。最も単純な(通常は見当違いの)アプローチでは、構造を内部で同期し、非アトミックな check-then-act 操作を危険なままにします。

LRUキャッシュでは、構造全体を少なくともある程度認識する必要があります。メンバーを削除するタイミングを決定するには、メンバーの数やメンバーのサイズなどが必要であり、その後、要素の読み取り、追加、削除の同時試行と追い出しを調整できる必要があります。 <!> quot; main <!> quotへの同時アクセスに必要な同期を削減しようとしています。構造はあなたの立ち退きメカニズムと戦い、あなたの立ち退きポリシーを保証の精度を下げます。

現在受け入れられている回答には、<!> quot;エントリを削除したい場合<!> quot;が記載されています。そこには摩擦があります。エントリを削除するタイミングはどのようにわかりますか?この決定を行うために一時停止する必要がある他の操作はどれですか?

マップをCollections.synchronizedMap()でラップします。追加のメソッドを呼び出す必要がある場合は、この呼び出しから返されたマップでsynchronizeを呼び出し、元のマップで元のメソッドを呼び出します(例についてはjavadocsを参照)。キーなどを反復処理する場合も同様です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top