シングルトンモードの実装(5種類)
一般的に使用されています:
空腹のスタイル(安全で高いコール効率が高くなりますが、遅延した方法でロードすることはできません)
怠zyなスタイル(スレッドセーフ、低コール効率、遅延でロードできます)
他の:
二重検出ロックタイプ(JVMの基礎となる内部モデルにより、問題が時々発生し、構築および使用されません)
静的な内部クラス(スレッドセーフ、高コール効率ですが、遅延した方法でロードできます)
シングルトンを列挙します(スレッドセーフ、高コール効率、遅延でロードすることはできません)
空腹の男のシングルトンの特定のコードは次のとおりです。
パッケージcom.lcx.mode; /** * *空腹の人々のシングルトン。このオブジェクトが将来使用されているかどうかに関係なく、最初からこのオブジェクトのインスタンスを作成します。 *必要に応じて、作成されたインスタンスオブジェクトを返すため、比較的空腹であるため、これは空腹の人々のシングルトンと呼ばれます。 * @author qq1013985957 * */ public class singletonhanger {private static final singletonhanger instance = new Singletonhanger(); private singletonhanger(){} public static singletonhanger getInstance(){return instance; }} /***怠zyなハンスタイルのシングルトンは、シングルトンオブジェクトが必要な場合、唯一のシングルトンオブジェクトを作成し、後で再び呼び出します。また、返されたシングルトンオブジェクトは、最初に作成されたシングルトンオブジェクトです*静的メンバーを初期化してnullにし、シングルトンが取得されたときに作成します。 * @author qq1013985957 * */ class singletonlazy {private static singletonlazy instance = null; private singletonlazy(){} /***この方法で実装されているシングルトンは、複数のスレッドでは使用できません。複数の行が同時にIFメソッドを入力できるため、複数のシングルトンオブジェクトが生成されます。 * @return */ public static singletonlazy getInstance1(){if(instance == null){instance = new singletonlazy(); } returnインスタンス; } /***誰もが同期を考えるでしょう。同期方法は、マルチスレッドのSingleton*を実装できますが、この方法は望ましくなく、パフォーマンスに深刻な影響を与えます。この方法は、シングルトンを取得するたびにチェックする必要があるため、同期コードブロックのみを使用して同期を実現できます。 * @return */ public static synchronized singletonlazy getInstance2(){if(instance == null){instance = new singletonlazy(); } returnインスタンス; } /***同期コードブロックを使用して、IFメソッドの同期コードブロックを使用してシングルトンが存在するかどうかを判断し、同期コードブロックを再度チェックして、シングルトンが生成されたかどうかを確認します。 *これは、インターネット上でロックするダブルチェックの方法 * @return */ public static synchlonized singletonlazy getInstance3(){if(instance == null){synchronized(singletonlazy.class){if(instance == null){instance = new singletonlazy(); }}} return instance; }} /***列挙を使用してSingletonモードを実装します。これは、特定の状況に応じて効果的なJava*インスタンス化で使用する推奨方法でもあります。 Enumsに精通していない学生の場合、私のブログJava Enumerationクラスの予備的な理解を参照できます。 *その利点:それはより簡潔であり、複雑なシーケンスと反射攻撃に直面しても、複数のインスタンス化を完全に防ぐための無料のシリアル化メカニズムを提供します。 * @author qq1013985957 * */ enum singletionenum {singletionenum( "singleton enum");プライベート文字列str; private singletionenum(string str){this.setstr(str); } public string getStr(){return str; } public void setStr(string str){this.str = str; }}上記のシングルトンパターンはテストされていません。それをテストして、オブジェクトのハッシュコードが同じオブジェクトであるかどうかを判断するために一貫しているかどうかを判断できます。
邪悪で怠zyな方法は、反射が複数のインスタンスを実装するのを防ぐことはできません。リフレクションを通じて、アクセス可能な方法を設定します。セットアクセス可能な方法は、プライベートコンストラクターを呼び出すことができます。 2番目のインスタンスを作成するように求められたときに、コンストラクターを変更して例外をスローすることができます。
実際、これはシングルトンを保証することはできません。シリアル化の後、脱介入は新しいインスタンスを作成し、SingletonクラスにReadResolve()メソッドを追加してそれを防ぐことができます。
怠zyなマンスタイルのシングルトンコードは次のとおりです。
パッケージcom.lcx.mode; java.io.fileをインポートします。 java.io.fileinputStreamをインポートします。 java.io.fileoutputStreamをインポートします。 java.io.objectinputStreamをインポートします。 java.io.objectOutputStreamをインポートします。 java.io.serializableをインポートします。 java.lang.reflt.constructorをインポートします。 Import java.lang.Reflect.InvocationTargetException; /***シングルトンオブジェクトが必要なときに、怠zyな男スタイルのシングルトンが作成されます。 Singletonオブジェクトが必要な場合、後で再び呼び出されます。返されたシングルトンオブジェクトは、最初に作成されたSingletonオブジェクトでもあります*静的メンバーをNullに初期化し、Singletonが取得されたときに作成するため、Lazy Manスタイルと呼ばれます。 * @author qq1013985957 * */ public class singletonはシリアル化可能{/ ** * */ private static final long serialversionuid = -5271537207137321645l;プライベート静的シングルトンインスタンス= null; private static int i = 1; private singleton(){ / ***反射攻撃を防止し、コンストラクターを一度実行して呼び出すだけで、例外を2回目にスローします* / if(i == 1){i ++; } else {throw new runtimeException( "コンストラクターは1回だけ呼び出すことができます"); } system.out.println( "Singletonのプライベートコンストラクターに電話); } /***同期コードブロックを使用して、IFメソッドの同期コードブロックを使用してシングルトンが存在するかどうかを判断し、同期コードブロックを再度チェックして、シングルトンが生成されたかどうかを確認します。 *これは、インターネットがダブルチェックロック方法と呼ぶもの * @return */ public static同期Singleton getInstance(){(instance == null){synchronized(singleton.class){if(instance == null){instance = new Singleton(); }} return instance; } /***新しいシングルトンオブジェクトの生成を防ぐ。これは、本の効果的なJavaの本で言われていることです。この方法を防ぐことができます。特定の詳細がわかりません * @return */ private object readResolve(){return instance; } public static void main(string [] args)throws exception {test1(); test2(); } / ***テスト避難所はまだSingleton Mode* @Throws Exception* / public Static void test2()Throws Exception {Singleton S = Singleton.getInstance(); objectOutputStream objectOutmoutputStream = new objectOutputStream(new FileOutputStream(new File( "e://singleton.txt"))); ObjectOutputStream.WriteObject(s); ObjectInputStream ObjectInputStream = new ObjectInputStream(new FileInputStream(new File( "e://singleton.txt")))); Object readObject = objectInputStream.ReadObject(); Singleton S1 =(Singleton)ReadObject; system.out.println( "s.hashcode():"+s.hashcode()+"、s1.hashcode():"+s1.hashcode()); ObjectOutputStream.Flush(); ObjectOutputStream.Close(); ObjectInputStream.Close(); ObjectInputStream.Close(); } / ***テストリフレクション攻撃* @throws例外* / public static void test1(){singleton s = singleton.getInstance();クラスC = singleton.class;コンストラクターPrivateConstructor; try {privateconstructor = c.getDeclaredConstructor(); privateconstructor.setAccessible(true); privateconstructor.newinstance(); } catch(Exception e){e.printstacktrace(); }}}反射攻撃の結果を確認します:
ReadResolveメソッドの結果が追加されていない場合:
ReadResolveメソッドを追加した結果:
読んでくれてありがとう、私はそれがあなたを助けることができることを願っています。このサイトへのご支援ありがとうございます!