javaのよくある面接試験問題の一例モード

3707 ワード

javaの一例モード
単例モードといえば、多くの面接問題の中に出てくる問題だと信じています。皆さんも基本的に知っていますが、どうすれば面接官に目を光らせられますか?次に解析の一例モードを行います。知識庫を埋めてまず簡単な一例モードを言います。
package com.youzhong.test;

public class SingletonModel {

	private static SingletonModel instance = new SingletonModel();  
    
    private SingletonModel(){}  
    //       ,   public static    
    public static SingletonModel getInstance(){  
        return instance;  
    }  
	public static void main(String[] args) {
		SingletonModel danli = SingletonModel.getInstance();
	}
	
}
    このクラスのオブジェクトを任意に作成するためには、このクラスの構造方法はプライベートであることを保証しなければなりません。このように外部クラスはこのタイプのオブジェクトを作成できません。また、お客様のオブジェクトに次の例のオブジェクトを提供するためには、グローバルなアクセスポイントを提供し、この時点のスレッドをpublic staticで修飾する必要があります。複数のスレッドがgetInstance()にアクセスすると、複数の異なるオブジェクトが初期化されない。これはJVMがこのようなローディングを行っている場合、static属性の初期化は一つのスレッドでのみ実行され、一回だけ実行されるからである。お客様はこの一例のモード方法を使用しています。Singleton Model singleton=Sigleton.getInstance()単純な一例モードのように見えますが、システムの中で一つのクラスが最大で一つのインスタンスしか存在しないことを保証するには、単一の例モードが必要です。このような状況は、例えばキャッシュ・プール、データベース接続プール、スレッド・プール、アプリケーション・サービスの実力などのようなアプリケーションでよく出会う。マルチスレッドの環境では、インスタンスの一意性を保証するために、実は簡単ではない。一例のモードのアップグレード版は、性能を考慮して、初期化クラスを行う際には、実際のオブジェクト(static属性はクラスをロードする時に初期化されます)を実行しません。初めてのインスタンスの時にのみ実装されますが、どうすればいいですか?
package com.youzhong.test;

class UnThreadSafeSingleton{  
	private static UnThreadSafeSingleton instance = null;  
	private UnThreadSafeSingleton(){}  
	  
	public static UnThreadSafeSingleton getInstance(){  
		if(instance == null){ //              
			instance = new UnThreadSafeSingleton();  
		}  
		return instance;  
	}  
}
上記の遅延作成例では、スレッドが安全ではなく、高合併の環境において複数の異なるインスタンスオブジェクトが出現します。これがc++で作成された場合、他のスレッドで生成されたオブジェクトを無視して、手を動かして彼らを回収しないとメモリ漏れが発生します。この問題を解決するには、この方法にsynchronizedキーワードを追加する必要があります。コードは以下の通りです。
package com.youzhong.test;

class ThreadSafeSingleton{  
	private static ThreadSafeSingleton instance = null;  
	private ThreadSafeSingleton(){}  
	  
	//  ,                   
	public synchronized static ThreadSafeSingleton getInstance(){  
		if(instance == null){  
			instance = new ThreadSafeSingleton();  
		}  
		return instance;  
	}  
}  
Double-Check Locking上ではマルチスレッドアクセスの安全を実現していますが、マルチスレッドの高同時アクセスの場合は、この方法にsynchronizedキーワードを追加することで、パフォーマンスが大きく低下します。キーワードのsynchronizedキーワードを使ってget Instance全体を同期する必要はありません。私たちはこのオブジェクトを実装する論理が一つのスレッドで実行されることを保証しさえすればいいです。戻りのコードは同期する必要がありません。このアイデアに沿ったコードは以下の通りです。
package com.youzhong.test;

class DoubleCheckSingleton{  
	private volatile static DoubleCheckSingleton instance = null;  
	
	private DoubleCheckSingleton(){}  
	
	public static DoubleCheckSingleton getInstacne(){  
	
		if(instance == null){  
		  synchronized(DoubleCheckSingleton.class){  
			  //Double Check if it is create  
			  if(instance == null){  
				  instance = new DoubleCheckSingleton();  
			  }  
		  }  
		}  
		return instance;  
	}  
} 
正式に二回の検査を使ったので、私達はdouble-check locking属性instanceと呼びます。volatileはsynchronizedの視認性の特徴を持っています。つまりスレッドは自動的にvolatile変数の最新値を発見できます。
Initialization demand Holder怠け者ローディングモードの実現コードは以下の通りです。
class LazyLoadedSingleton{  
	  
	private LazyLoadedSingleton(){}  
	  
	private static class LazyHolder{  
		private static final LazyLoadedSingleton singletonInstance = new LazyLoadedSingleton();  
	}  
	public static LazyLoadedSingleton getInstance(){  
		return LazyHolder.singletonInstance;  
	}  
} 
JVMがLazyLoadedSingleton類をロードする時、このクラスはstatic属性がないため、すべてのロードが完了したら戻ります。初めてgetInstanceを呼び出す方法は、JVMだけがLazyHolderクラスをローディングします。これはstatic属性singleton Instanceを含んでいますので、先にこの変数を初期化します。前の説明によると、JVMは一つのスレッドだけでstaticを初期化することができます。これにより、スレッドの安全を保証し、遅延負荷をサポートする単一の例のモードが実現される。一回聞いてみてください。一回の収穫です。ハイヒールとランニングシューズがありますように。お酒もお茶も飲みます。