コードのデバッグ中に状況を発見しました。つまり、memcached の接続を確認したところ、接続数が常に 100 程度に維持されていることがわかりました。もちろん、memcached の接続数はデフォルトで 1024 であるため、これは問題ないようです。しかし、私が考えているのは、なぜ 100 個ほどあるのかということです。memcachedclient はシングルトン モードで生成されるため、メイン コードは次のとおりです。
private MemcachedClientFactory(){
}
private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String サーバー){
this.memcachedConnectionBuilder= memcachedConnectionBuilder;
this.servers=サーバー;
}
public static MemcachedClient createClient(){
if(memcachedClient==null){
this.memcahcedClien= new MemcachedClient(memcachedConnectionBuilder.build(),AddrUtil.get(servers));
}
this.memcahcedClient を返します。
}
}
}
元の質問に戻りますが、なぜ 100 を超える接続があるのでしょうか?
上記の書き方で本当に接続が1つしか生成されないことが保証できるのでしょうか?明らかに違いますが、なぜですか?マルチスレッド同時実行!問題はここにあります。複数のスレッドが同時に createClient() メソッドに入り、すべてのスレッドが memcachedClient が null であると判断すると、複数の接続が生成されます。はあ、問題が見つかりました。
改善する:
これで問題ありません。変更は非常に簡単です。プログラムに問題はなく、接続は 1 つだけであることが保証されています。
しかし、この問題を脇に置いて、シングルトン モードでの同時実行の問題を解決する方法について深く考え続けることができます。
要約すると、シングルトン モードで同時実行性の問題を解決するには、大まかに 3 つの方法があります。
1. 遅延インスタンス化を使用せず、早期インスタンス化を使用します。
つまり、プログラムは次のように書き換えられます。
パブリック静的シングルトン getInstance(){
インスタンスを返します。
}
}
この際、jvmはクラスロード時に即座にインスタンスを作成するので、インスタンス作成の負担が大きくないこと、パフォーマンスについてはあまり考えず、インスタンスが確実に生成されることを確認していることが前提となります。使用されます。実際、私の以前のコードは次のように使用することもできます。
private MemcachedClientFactory(){
}
private MemcachedClientFactory(MemcachedConnectionBuilder memcachedConnectionBuilder, String サーバー){
this.memcachedConnectionBuilder= memcachedConnectionBuilder;
this.servers=サーバー;
}
public static MemcachedClient createClient(){
this.memcahcedClient を返します。
}
}
}
ただし、問題がないように見えますが、隠れた危険があります。つまり、誰かが誤って memcachedClient.shutdown() メソッドを呼び出すと、プログラム全体が新しい memcachedClient を生成できなくなります。もちろん、これは極端なケースですが、コードの堅牢性を高めるために、次のように変更できます。
2. synchronized キーワードを使用するだけです。
これを行うと同期の問題が確実に発生する可能性がありますが、synchronized を使用するオーバーヘッドが非常に高く、パフォーマンスに重大な影響を与えることがわかっているため、これを使用する前提として、このメソッドを頻繁に呼び出さないこと、または作成のオーバーヘッドが発生しないことを確認する必要があります。この例は特別なものではありません。改善できるかどうかは以下を参照してください。
3.「二重チェックロック」を使用し、getInstance で同期を使用する
プライベートシングルトン(){};
パブリック静的シングルトン getInstance(){
if(インスタンス==null){
同期済み (Singleton.class){
if(インスタンス==null){
インスタンス=新しいシングルトン();
}
}
}
インスタンスを返します。
}
}