[2つの実装Singletonパターン - 実装の7種類] [安全面の問題が提供する証明]

「安全オファーを証明」リスト


I.用語集

シングルトン(Singletonパターン)は、Javaのデザインパターンの最も簡単なの一つです。デザインパターンのこのタイプのオブジェクトを作成するための最良の方法を提供し、スキーマを作成します属します。このモデルは、単一のオブジェクトが作成されていることを保証しながら、独自のオブジェクトを作成するための責任がある単一のクラスが含まれます。このクラスは、オブジェクトが直接アクセスできる、オブジェクトクラスのインスタンスにアクセスするための唯一の方法を提供します。

注意:

  • 1、一つだけシングルトンクラスのインスタンス。
  • 2、シングルトンクラスには、独自のインスタンスを作成する必要があります。
  • 3、シングルトンクラスは、他のすべてのオブジェクトにこの例を提供しなければなりません。

いくつかの2つの単一モードの実装の実施例

基本的なスタイルで空腹男と怠惰な人間の違いとは、クラス内か外で独自のオブジェクトを作成します。そして民営化のオブジェクトを宣言する必要が、コンストラクタは、新しい外部オブジェクトへのアクセスを通じてだけでなく、この方法を民営化する必要があります。中国風の言葉は、単にクラスのgetInstance()メソッドは、新しいオブジェクトになります呼び出し、オブジェクトを宣言(彼は空腹だったので)、怠惰なスタイル空腹宣言され、オブジェクトを作成します。

  1、怠惰なスタイル、スレッドセーフ 

  説明:これは、最大の問題は、マルチスレッドをサポートしていません実現し、実装の最も基本的な方法です。同期一切ロックが存在しないので、それほど厳密にそれを言えば、シングルトンではありません。明らかに、このよう遅延読み込み、適切にマルチスレッドでスレッドセーフ、できない作業を必要としません。

public static class Singleton02{
		private static Singleton02 instance= null;
		
		private Singleton02() {
			
		}
		
		public static Singleton02 getInstance() {
			if(singLeton == null) {
				instance= new Singleton02();
			}
			
			return instance;
		}
	}

2、怠惰なスタイル、スレッドセーフ

          説明:この方法で良い遅延ロードを持って、マルチスレッドでうまく機能することができ、しかし、例99%が同期を必要としない、非常に低い効率です。
         長所:最初の呼び出しが初期化されたが、メモリを無駄にしないようにします。
         短所:シングルケースを確実にするために、同期ロックする必要がありますが、ロックは、効率に影響を与えます。パフォーマンスのgetInstance()アプリケーションが(あまり頻繁に使用している)重要ではありません。

public static class Singleton03{
		private static Singleton03 instance= null;
		
		private Singleton03() {
			
		}
		
		public static synchronized  Singleton03 getInstance() {
			if(singLeton == null) {
				instance= new Singleton03();
			}
			return instance;
		}
	}

3、空腹中国風のスレッドセーフ

説明:このように一般的に使用されるが、発生しやすいごみはオブジェクト。
           長所:ロックされていない、効率が向上します。
           短所:クラスがメモリを無駄にロードされたときに初期化。
           クラスのロードは、シングルトンモードでそれらのほとんどは、getInstanceメソッドを多数呼び出しているされているが、それは決定できない原因がありますが、クラスローダのメカニズムは、同期の問題マルチスレッドは、しかし、クラスのインスタンスへのインスタンスが一度にロードされている回避基づいています明らかに、インスタンスの初期化遅延ロードの効果に達しなかった他の方法(または他の静的メソッド)クラスローダをリードは、あります。

public static class Singleton01{
		private static final Singleton01 INSTACNE= new Singleton01();
		
		private Singleton01() {
			
		}
		
		public static  Singleton01 getInstance() {
			return INSTACNE;
		}
	}

図4に示すように、二重ロック検出/ダブルチェックロック(DCL、即ち、ダブルチェックロック)、遅延型スレッドセーフからJDK1.5

説明:このデュアルモードロック機構、および安全なマルチスレッドには、高い性能を維持することができます。パフォーマンスのgetInstance()は、アプリケーションにとって非常に重要です。

public static class Singleton07{
		private volatile static Singleton07 instance = null;
		
		private Singleton07() {
			
		}
		
		public static Singleton07 getInstance() {
			if(instance == null) {
				synchronized (Singleton07.class) {
					if(instance == null) {
						instance = new Singleton07();
					}
				}
			}
			return instance ;
		}
		
	}

5、静的な内部クラス、怠惰なスタイル、スレッドセーフ

説明:この方法で同じ効果を得ることができ、二重ロックモードをチェックしますが、実装が簡単です。遅延を使用して静的フィールドの初期化は、このモードではなく、二重ロック検出モードを使用すべきです。この実施形態は、静的なフィールドに適用される遅延は、インスタンスのフィールドを初期化するために必要な場合、二重ロック検出モードを使用することができます。
          このように同じクラスローダ機構の使用は、初期化インスタンスにその一つだけスレッドを確保するために、それは今である第三の方法が異なっている:長いシングルトンクラスは、インスタンスがインスタンス化されロードされると最初の3つの方法が(遅延ロードに達していません効果)が、このアプローチは、シングルトンクラスロードされ、インスタンスが初期化されなくてもよいです。SingletonHolderクラスがアクティブに使用されていないので、明示的な呼び出しによってgetInstanceメソッドは、明示的にインスタンス化インスタンスにSingletonHolderクラスをロードします。あなたは、インスタンスはリソースを消費するインスタンス化した場合、想像し、その一方、クラスはシングルトン、シングルトンクラスをインスタンス化されるときに、彼らが主導権をも可能にするために、他の場所で使用することができることを保証することはできませんので、ロードしたくない、遅延読み込みにそれをしたいですロードされ、明らかに不適切なインスタンス化インスタンスに、この時間。今回は、方法の最初の3種類に比べて、このように、それは非常に合理的です。

public static class Singleton05{
		private static final class SingletonHold{
			private static final Singleton05 INSTANCE= new Singleton05();
		}
		private Singleton05() {
			
		}
		
		public static Singleton05 getInstance() {
			return SingletonHold.INSTANCE;
		}
	}

6、列挙、飢えスタイルの後、スレッドセーフJDK1.5

説明:この実装は、広く採用されていないが、これは、シングルモードの実施例を実現するための最良の方法です。これは、よりコンパクトな、絶対の複数のインスタンスを防止するための自動サポートシリアル化メカニズムです。
           このアプローチは、それがマルチスレッド同期の問題を避けることができるだけでなく、効果的なJavaの作成者ジョシュ・ブロッホ方法を提唱するだけでなく、自動的に絶対に複数のインスタンス化を防ぐため、直列化復元は、新しいオブジェクトを再作成を防止するために直列化メカニズムをサポートしています。しかし、この方法でのみ書き込みが実際には、ほとんど使用されない、助けることはできませんが、不思議な感じ、JDK1.5後に列挙型のプロパティに参加しました。反射によってプライベートコンストラクタを呼び出すために攻撃しません。

	public enum Singleton06{
		INSTANCE;
		
		public void whateverMethod() {
			
		}
	}

7、静的ブロック、飢え式

説明:クラス変数を作成し、静的なブロックがインスタンス化されます。コードの静的ブロックは、クラスを使用する前に実行されているので、この機能は、単一の実施の形態を用いて実現することができます。方法の第三の前に単一のインスタンスを作成するために静的変数を使用することです。

	public static class Singleton04{
		
		private static Singleton04 instance= null;
		
		static {
			instance= new Singleton04();
		}
		
		private Singleton04() {
			
		}
		
		public static Singleton04 getInstance() {
			return instance;
		}
	}

第三に、コードのテスト

package com.acm.firstmonth;

import com.acm.firstmonth.SingLeton.Singleton01;
import com.acm.firstmonth.SingLeton.Singleton02;
import com.acm.firstmonth.SingLeton.Singleton03;
import com.acm.firstmonth.SingLeton.Singleton04;
import com.acm.firstmonth.SingLeton.Singleton05;
import com.acm.firstmonth.SingLeton.Singleton06;
import com.acm.firstmonth.SingLeton.Singleton07;

public class Test02 {
	/**
	 * 饿汉式 线程安全  
	 * @author zc
	 *
	 */
	public static class Singleton01{
		private static final Singleton01 INSTANCE = new Singleton01();
		
		private Singleton01() {}
		
		public static Singleton01 getInstance() {
			return INSTANCE;
		}
	}
	/**
	 * 饿汉式 线程安全
	 * @author zc
	 *
	 */
	public static class Singleton02{
		private static Singleton02 instance ;
		static {
			instance = new Singleton02();
		}
		
		private Singleton02() {}
		
		public static Singleton02 getInstance() {
			return instance;
		}
	}
	/**
	 * 饿汉式  线程安全  JDK1.5+
	 * @author zc
	 *
	 */
	public enum Singleton03{
		INSTANCE;
		
		public void whateverMethod() {}
	}
	/**
	 * 懒汉式 线程不安全
	 * @author zc
	 *
	 */
	public static class Singleton04{
		private static Singleton04 instance = null;
		
		private Singleton04() {}
		
		
		public static Singleton04 getInstance() {
			if(instance == null) {
				return instance = new Singleton04();
			}
			return instance;
		}
	}
	/**
	 * 懒汉式 线程安全
	 * @author zc
	 *
	 */
	public static class Singleton05{
		private static Singleton05 instance = null;
		
		private Singleton05() {}
		
		public static synchronized Singleton05 getInstance() {
			if(instance == null) {
				instance = new Singleton05();
			}
			return instance;
		}
	}
	/**
	 * 静态内部类 线程安全  懒汉式
	 * @author zc
	 *
	 */
	public static class Singleton06{
		
		private static class SingletonHold{
			private static final Singleton06 INSTANCE = new Singleton06();
		}
		
		private Singleton06() {}
		
		public static Singleton06 getInstance() {
			return SingletonHold.INSTANCE;
		}
	}
	/**
	 * 二重锁 懒汉式 线程安全
	 * @author zc
	 *
	 */
	public static class Singleton07{
		private volatile static  Singleton07 instance = null;
		
		private Singleton07() {}
		
		public static Singleton07 getInstance() {
			if(instance == null) {
				synchronized(Singleton07.class) {
					if(instance == null) {
						instance = new Singleton07();
					}
				}
			}
			return instance;
		}
	}
	
	public static void main(String[] args) {
		//饿汉式
		System.out.println( Singleton01.getInstance() == Singleton01.getInstance());
		System.out.println( Singleton02.getInstance() == Singleton02.getInstance());
		System.out.println( (Singleton03.INSTANCE == Singleton03.INSTANCE));
		//懒汉式
		System.out.println( Singleton04.getInstance() == Singleton04.getInstance());
		System.out.println( Singleton05.getInstance() == Singleton05.getInstance());
		System.out.println( Singleton06.getInstance() == Singleton06.getInstance());
		System.out.println( Singleton07.getInstance() == Singleton07.getInstance());
		
	}
	
}

 

公開された14元の記事 ウォンの賞賛1 ビュー5526

おすすめ

転載: blog.csdn.net/Vpn_zc/article/details/84100878