1。はじめに
この記事では、高性能Javaキャッシュライブラリであるカフェインを見てみましょう。
キャッシュとMAPの根本的な違いの1つは、キャッシュが保存されたアイテムをリサイクルできることです。
リサイクルポリシーは、指定された時間にオブジェクトを削除することです。この戦略は、キャッシュライブラリの重要な機能であるキャッシュヒット率に直接影響します。
カフェインは、ウィンドウのティニルフーリサイクル戦略の使用により、ほぼ最適なヒット率を提供します。
2。依存
pom.xmlにカフェイン依存性を追加する必要があります:
<Dependency> groupId> com.github.ben-manes.caffeine </groupid> <artifactid> caffeine </artifactid> <バージョン> 2.5.5 </version> </dependency>
Maven Centralでカフェインの最新バージョンを見つけることができます。
3.キャッシュを入力します
カフェインの3つのキャッシュ充填戦略、マニュアル、同期荷重、非同期負荷を見てみましょう。
まず、キャッシュに保存される値タイプのクラスを書きます。
class dataObject {プライベート最終文字列データ。 private static int objectcounter = 0; //標準コンストラクター/ゲッターpublic static data object get(string data){objectcounter ++;新しいdataObject(data)を返します。 }}3.1。手動の詰め物
この戦略では、キャッシュを取得する前に手動で値をキャッシュに入れました。
キャッシュを初期化しましょう:
cache <string、data object> cache = caffeine.newbuilder().expireafterwrite(1、timeunit.minutes).maximumsize(100).build();
これで、getifpresentメソッドを使用して、キャッシュからいくつかの値を取得できます。この値がキャッシュに存在しない場合、この方法はnullを返します。
文字列key = "a"; data object dataObject = cache.getifpresent(key); assertnull(dataObject);
PUTメソッドを使用して、キャッシュを手動で埋めることができます。
cache.put(key、dataObject); dataObject = cache.getifpresent(key); assertnotnull(dataObject);
また、GETメソッドを使用して値を取得することもできます。これは、パラメーターキーをパラメーターとして渡す関数を渡すこともできます。キーがキャッシュに存在しない場合、関数は、計算後にキャッシュに挿入されるフォールバック値を提供するために使用されます。
dataObject = cache .get(key、k-> dataObject.get( "for a")); assertnotnull(dataObject); assertequals( "data for a"、dataObject.getData());
GETメソッドは、原子的に計算を実行できます。これは、複数のスレッドが同時に値を要求したとしても、計算を1回だけ行うことを意味します。これが、Getを使用することがGetifpresentよりも優れている理由です。
いくつかのキャッシュされた値を手動で無効にする必要がある場合があります。
cache.invalidate(key); dataObject = cache.getifpresent(key); assertnull(dataObject);
3.2。同期負荷
キャッシュをロードするこの方法は、値の初期化に使用される関数と同様の手動戦略を使用してGETメソッドを使用します。使い方を見てみましょう。
まず、キャッシュを初期化する必要があります。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().maximumsize(100).expireafterwrite(1、timeunit.minutes).build(k-> dataObject.get( "for" + k));
これで、GETメソッドを使用して値を取得できます。
dataObject dataObject = cache.get(key); assertnotnull(dataObject); assertequals( "for" + key、dataObject.getData());
GetAllメソッドを使用して、次の値を取得することもできます。
map <string、data object> data objectmap = cache.getall(arrays.aslist( "a"、 "b"、 "c")); Assertequals(3、dataObjectMap.size());
基礎となるバックエンドの初期化関数から値を取得します。ビルドメソッドに渡されます。これにより、値をアクセスする主なファサードとしてキャッシュを使用できます。
3.3。非同期負荷
このポリシーは以前と同じことを行いますが、非同期に操作を実行し、値を含む完全な既製を返します。
asyncloadingcache <string、data object> cache = caffeine.newbuilder().maximumsize(100).expireafterwrite(1、timeunit.minutes).buildasync(k-> data object.get( "for" + k));
Get and Getallメソッドを同じ方法で使用できます。
文字列key = "a"; cache.get(key).thenaccept(data object-> {assertnotnull(dataObject); assertequals( "for" + key、dataObject.getData());}); cache.getall(arrays.aslist( "a"、 "b"、 "c"))))。CompleteFutureには多くの有用なAPIがあり、この記事ではもっと多くのことを得ることができます。
4。価値回復
カフェインには、サイズベース、時間ベース、および参照ベースの3つの価値回復戦略があります。
4.1。サイズに基づくリサイクル
このリサイクル方法は、構成されたキャッシュサイズの制限を超えるとリサイクルが発生することを前提としています。サイズを取得するには2つの方法があります。キャッシュ内のオブジェクトをカウントするか、重量を取得します。
キャッシュ内のオブジェクトを計算する方法を見てみましょう。キャッシュが初期化されると、そのサイズはゼロに等しくなります。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().maximumsize(1).build(k-> dataObject.get( "for" + k)); Assertequals(0、cache.estimatedsize());
値を追加すると、サイズは大幅に増加します。
cache.get( "a"); Assertequals(1、cache.estimatedsize());
2番目の値をキャッシュに追加できます。これにより、最初の値が削除されます。
cache.get( "b"); cache.cleanup(); Assertequals(1、cache.estimatedsize());
キャッシュサイズを取得する前に、クリーンアップ方法を呼び出すことに言及する価値があります。これは、キャッシュのリサイクルが非同期に実行されるためであり、このアプローチはリサイクルが完了するのを待つのに役立ちます。
また、計量機能を渡して、キャッシュサイズを取得することもできます。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().maximumweight(10).weighter((k、v) - > 5).build(k-> dataObject.get( "for" + k)); Assertequals(0、cache.estimatedsize()); cache.get( "a"); Assertequals(1、cache.estimatedsize()); cache.get( "b"); assertequals(2、cache.estimatedsize());
重量が10を超えると、値はキャッシュから削除されます。
cache.get( "c"); cache.cleanup(); assertequals(2、cache.estimatedsize());
4.2。時間の回復に基づいています
このリサイクル戦略は、エントリの有効期限に基づいており、3つのタイプがあります。
ExpireAfterAccessメソッドを使用して、アクセス後の有効期限ポリシーを構成しましょう。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().expireafteraccess(5、timeunit.minutes).build(k-> dataObject.get( "for" + k));
write後の有効期限ポリシーを構成するために、expireafterwriteメソッドを使用します。
cache = caffeine.newbuilder().expireafterwrite(10、timeunit.seconds).weakkeys().weakvalues().build(k-> dataObject.get( "for" + k));
カスタムポリシーを初期化するには、有効期限インターフェイスを実装する必要があります。
cache = caffeine.newBuilder()。 currentDuration; @Override Public long expireafterRead(String key、long current -currentduration){return currentduration;4.3。参照に基づくリサイクル
キャッシュされたキー値のごみ収集を有効にするようにキャッシュを構成できます。これを行うには、キーと値を弱い参照として構成し、ガベージコレクションのソフト参照のみを構成できます。
オブジェクトへの強い参照がない場合、WeakRefenceを使用すると、オブジェクトのごみ収集が可能になります。 Softreferenceは、JVMのグローバルな最小限に使用されているポリシーに基づいて、オブジェクトがゴミ収集を可能にします。 Java Citationsの詳細については、こちらをご覧ください。
caffeine.weakkeys()、caffeine.weakvalues()、およびcaffeine.softvalues()を使用して各オプションを有効にする必要があります。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().expireafterwrite(10、timeunit.seconds).weakkeys().weakvalues().build(k-> dataObject.get( "for" + k)); cache = caffeine.newbuilder().expireafterwrite(10、timeunit.seconds).softvalues().build(k-> dataObject.get( "for" + k));
5。更新
キャッシュは、定義された期間後にエントリを自動的に更新するように構成できます。 Refreshafterwriteメソッドの使用方法を見てみましょう。
caffeine.newbuilder().Refreshafterwrite(1、timeUnit.minutes).build(k-> dataObject.get( "for" + k));
ここでは、expirefterとrefreshafterの違いを理解する必要があります。期限切れのエントリが要求されると、ビルド関数が新しい値を計算するまで実行がブロックされます。
ただし、エントリを更新できる場合、キャッシュは古い値を返し、値を非同期にリロードします。
6。統計
カフェインには、キャッシュの使用量を記録する方法があります。
LoadingCache <String、dataObject> cache = caffeine.newbuilder().maximumsize(100).recordstats().build(k-> dataObject.get( "for" + k)); cache.get( "a"); cache.get( "a"); Assertequals(1、cache.stats()。hitcount()); Assertequals(1、cache.stats()。misscount());
また、RecordStatsのサプライヤーに合格して、StatCounterの実装を作成する場合があります。このオブジェクトは、すべての統計関連の変化をプッシュします。
7。結論
この記事では、Javaのカフェインキャッシュライブラリに精通しています。キャッシュを構成して埋める方法、およびニーズに基づいて適切な有効期限または更新ポリシーを選択する方法を見ました。
この記事の例のソースコードは、GitHubで見つけることができます。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。