記事のディレクトリ
マルチスレッドまたは同時シナリオでの可変データのセキュリティ問題を解決し、ダーティデータの生成を回避するために、シングルトンモードをよく使用します。
この記事では、Javaマルチスレッドでのシングルトンパターンのさまざまな実装を簡単に要約し、これらのシングルトン実装の長所と短所を比較します。
記事の内容は、GaoHongyanによる「JavaMultithreadedProgrammingCoreTechnology」から抽出されています。
シングルトンモード分析
今すぐロード(空腹の男モード)
すぐにロード:クラスを使用する必要がある場合、オブジェクトはすでに作成されています。
hungry manモードは、メソッドを呼び出す前にインスタンスが作成されていることを意味します。サンプルコードは次のとおりです。
package test;
public class MyObject{
private static MyObject myObject = new MyObject();
private MyObject(){
}
public static MyObject getInstance(){
return myObject;
}
}
次のようにスレッドクラスMyThread.javaコードを作成します。
import test.MyObject;
public class MyThread extends Thread{
@Override
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}
実行メインクラスRun.javaを作成します。
import extthread.MyThread;
public class Run{
public static void main(String[] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
それを実行すると、出力されたhashCode(ハッシュコード、オブジェクトインスタンスの一意の識別子、各自のID番号に類似)が同じ値であることがわかります。上記のシナリオは、すぐに読み込まれるシングルトンデザインパターンです。
遅延読み込み(レイジーマンモード)
遅延読み込み:get()が呼び出されたときにインスタンスが作成されることを指します。
MyObject.java
package test;
public class MyObject{
private static MyObject myObject;
private MyObject(){
}
public static MyObject getInstance(){
//延迟加载
if(myObject == null){
myObject = new MyObject();
}
return myObject;
}
}
「遅延読み込み」はシングルトンデザインパターンを実装しますが、マルチスレッド環境では、上記の「遅延読み込み」コードは完全に間違っており、シングルトン状態をまったく維持できません。
レイジーマンモードはシングルトンソリューションを保証します
1.同期されたキーワードの実装
-
getInstance()メソッドをロックする:操作効率が低い
-
ロッククラス(Object.class):操作効率が低い
-
重要なコードの特定の部分に対する個別のロック同期:特定のマルチスレッドの安全上の問題がまだあります
-
DCLダブルチェックロック機構を使用
2.静的組み込みクラスはシングルトンモードを実装します
DCLは、マルチスレッドシングルトンのセキュリティ問題を解決できます。他の方法でも同じ効果を得ることができます。
3.シングルトンを実現するためのシリアル化と逆シリアル化
静的な組み込みクラスは、スレッドセーフの問題を解決できます。ただし、シリアル化されたオブジェクトに遭遇したときにデフォルトモードを使用して実行すると、多くの結果が得られます。
次のreadResolve()メソッドを使用して解決できます
4.静的コードブロックを使用してシングルトンを実装します
package test;
public class MyObject{
private static MyObject instance = null;
private MyObject(){
}
static{
instance = new MyObject();
}
public static MyObject getInstance(){
return instance;
}
}
5.列挙型列挙を使用してシングルトンを実現します
6.列挙型の使用を改善してシングルトンモードを実現します
上記の例は、「単一責任の原則」に違反し、次に改善できる列挙クラスを公開しています。
MyThread.javaのコードは次のとおりです
package extthread;
public class MyThread extends Thread{
@Override
public void run(){
for(int i=0; i< 5 ; i++){
System.out.println(MyObject.getConnection().hashCode());
}
}
}