前の記事では、プロキシクラス内でプロキシクラスがどのように生成されるかを分析しました。キャッシュメカニズムがプロキシ内で使用されていることがわかりました。提供されたクラスローダーとインターフェイスアレイに基づいてプロキシクラスをキャッシュに見つけることができる場合、プロキシクラスは直接返されます。それ以外の場合は、プロキシクロスファクトリーが呼び出され、プロキシクラスが生成されます。ここで使用されるキャッシュはセカンダリキャッシュであり、その第1レベルのキャッシュキーはクラスローダーに基づいて生成され、セカンドレベルのキャッシュキーはインターフェイス配列に基づいて生成されます。特定の内部メカニズムを詳細に説明するために、コードを直接投稿します。
//リファレンスリファレンスキュープライベート最終参照<k> refqueue = new ReferenceQueue <>(); //キャッシュの基礎となる実装、キーは第1レベルのキャッシュであり、値は2番目のレベルのキャッシュです。 nullをサポートするために、キータイプのマップは、objectprivate final concurrentmap <object、supprier <v >>> map = new concurrenthashmap <>(); //すべてのプロキシクラスジェネレーターが利用可能かどうかを記録するように設定されます。これは、キャッシュの有効期限メカニズムプライベート最終概念マップ<supprier <v>、boolean> reversemap = new concurrenthashmap <>(); //二次キャッシュキーを生成するファクトリー、keyactoryprivate final byunction <k、p、?> subkeyactory; bifunction <k、p、v> valueFactory; //コンストラクター、セカンダリキャッシュキーを生成する工場、および二次キャッシュ値を生成するファクトリーパブリックキャッシュ(bifunction <k、p、?> subkeyFactory <k、p、v> valueFactory){this.subkeyfactory = objects.requirenonlull(subrenonlull(subrenonlull); this.valueFactory = objects.requirenonnull(valueFactory);}まず、weakcacheのメンバー変数とコンストラクターを見てみましょう。 weakcacheキャッシュの内部実装は、concurrentMapを通じて完了します。メンバー変数マップは、セカンダリキャッシュの基礎となる実装です。 ReverseMapは、キャッシュの有効期限メカニズムを実装することです。 SubkeyFactoryは、セカンダリキャッシュキーの生成工場です。コンストラクターを通過します。ここで渡される値はプロキシクラスのキー要因であり、ValueFactoryはセカンダリキャッシュ値の生成工場です。コンストラクターを通過します。プロキシクラスのプロキシクロスファクトリーはここで渡されます。次に、WeakCacheのGETメソッドを見てみましょう。
public v get(k key、p parameter){//ここで実装する必要があるインターフェイスは、空のオブジェクトではありません。requirenonnull(parameter); //有効期限が切れたキャッシュexpungestaleentries(); //最初のレベルのキャッシュオブジェクトのキーとしてcachekeyにcashekeyにcachekeykeykey = cachekey.valueof(key、refqueue); //セカンダリキャッシュを取得<オブジェクト、サプライヤー<v >> valuesmap = map.get(cachekey); //対応する値がクラスローダーに基づいて取得されない場合if(valuesmap == null){// casに入れます。 // oldvaluesmapに値がある場合、それは配置が故障した場合を意味します(oldvaluesmap!= null){valuesmap = oldvaluesmap; }} //プロキシクラスによって実装されたインターフェイスアレイに基づいて2番目のレベルのキャッシュキーを作成し、key0、key1、key2、keyx object subkey = objects.requirenonnull(key、parameter))に分割されます。 //セカンダリキャッシュの値は、サブキーを通じて取得されます。サプライヤー<v> supply = valuesmap.get(subkey);工場工場= null; //このループはポーリングメカニズムを提供します。条件が偽の場合は、条件がtrueになるまで再試行し続けます(true){//サブキーから取得された値が空でない場合(サプライヤー!= null){//ここでは供給はここでは判断がありませんが、サプライヤー実装クラスv値= supplier.get() if(value!= null){return値; }} if(factory == null){// Subkey Factoryの対応する値として新しい工場インスタンスを作成= new Factory(key、parameter、subkey、valuesmap); } if(supplier == null){//ここでは、サブキーには対応する値がないことを意味します。サブキーの値としてsupplier = valuesmap.putifabsent(subkey、factory); if(supplier == null){//ここでは、工場がキャッシュサプライヤー=工場に正常に配置されることを意味します。 } //それ以外の場合、他のスレッドは期間中に値を変更する場合があります。その後、値をサブキーに割り当て続けることはありませんが、それらを直接使用して使用します} else {// } else {//失敗した交換、元の値supplier = valuesmap.get(subkey)を使用し続けます。 }}}}weakcacheのGETメソッドはロックと同期しないので、どのようにして糸の安全性を実現しますか?変更されたすべてのメンバー変数は同時マップを使用しているため、このクラスはスレッドセーフです。したがって、独自のスレッドの安全性を同時マップに委任し、GETメソッドは同期コードブロックを可能な限り削減し、WeakCacheのパフォーマンスを効果的に改善できます。クラスローダーはレベル1キャッシュのキーであるため、異なるクラスローダーがロードするクラスが異なるため、最初にクラスローダーに従ってフィルタリングできることがわかります。次に、インターフェイスアレイを使用して、セカンダリキャッシュのキーを生成します。ここでは、いくつかの最適化があります。ほとんどのクラスは1つまたは2つのインターフェイスを実装するため、セカンダリキャッシュキーはkey0、key1、key2、およびkeyxに分割されます。 Key0からKey2は、0〜2のインターフェイスが実装されていることを意味し、Keyxは3つ以上のインターフェイスが実装されることを意味します。実際、それらのほとんどはkey1とkey2のみを使用します。これらのキーの生成工場はプロキシクラスにあり、キーファクトリーはWeakCacheコンストラクターを通過します。ここでの第2レベルのキャッシュの値は工場のインスタンスであり、プロキシクラスの最終的な値は工場工場を通じて取得されます。
プライベートファイナルクラスの工場は、サプライヤー<v> {//レベル1キャッシュキーを実装し、クラスローダーに従ってプライベートファイナルKキーを生成します。 //プロキシクラスによって実装されたインターフェイスアレイプライベート最終Pパラメーター。 //レベル2キャッシュキー、インターフェイス配列に従ってプライベートファイナルオブジェクトサブキーを生成します。 //レベル2キャッシュプライベートファイナルConcurrentMap <object、supplier <v >> valuesmap; Factory(k key、p parameter、object subkey、concurrentmap <object、supplier <v >> valuesmap){this.key = key; this.parameter = parameter; this.subkey = subkey; this.valuesmap = valuesmap; } @Override public synchronized v get(){//ここでは、セカンダリキャッシュに再度行き、サプライヤーを取得して、工場自体のサプライヤー<v> supplier = valuesmap.get(subkey); if(supplier!= this){//ここで、サプライヤーが工場インスタンス自体であるかどうかを確認します。そうでない場合は、nullを返し、発信者にpollyを継続してretryにします。 } v値= null; try {// valueFactoryを委任してプロキシクラスを生成します。ここで、プロキシクラスの値は、入力プロキシクロスファクトリー= objects.requirenonnull(valueFactory.Apply(key、parameter))を介して生成されます。 }最後に{//プロキシクラスの生成が失敗した場合、このセカンダリキャッシュを削除します(value == null){valuesmap.remove(subkey、this); }} //値の値のみが空ではないことは、ここで到達することができますか? //プロキシクラスcachevalue <v> cachevalue = new cachevalue <>(value); //パッケージ化されたcachevalueを二次キャッシュに入れます。この操作は成功する必要があります。そうしないと、(valuesmap.replace(subkey、this、cachevalue)){// cachevalueを二次キャッシュに正常に置いた後、reversemap.put(cachevalue、boolean.true)をマークした場合、エラーが報告されます。 } else {throw new AssertionError( "ここに到達しないでください"); } //最後に、弱い参照で包まれていないプロキシクラスの返品値を返します。 }}内部工場クラスの工場をもう一度見てみましょう。また、同期されたキーワードを使用してGETメソッドが同期されていることがわかります。 GETメソッドを実行した後、最初にサブキーに対応するサプライヤーが工場自体であるかどうかを確認します。そうでない場合は、nullを返し、weakcache getメソッドは引き続き再試行します。それが実際に工場自体である場合、ProxyclassFactoryは委任されてProxyクラスを生成します。そこで、プロキシのプロキシクロースファクター内部工場が最終的にプロキシクラスを生成する理由を説明します。プロキシクラスを生成した後、弱い参照を使用してラップしてReverseMapに配置し、最後に元のプロキシクラスを返します。
これまでのところ、第1レベルのキャッシュとセカンドレベルのキャッシュ実装の原則を含むWeakCacheキャッシュの実装、および第2レベルのキャッシュキーを生成する原則と、プロキシクラスを最終的に生成する方法を詳細に明らかにしました。次の記事では、Proxygeneratorクラスにアクセスして、特定のプロキシクラスのバイトコード生成プロセスを確認します。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。