天天看點

java 單例模式之線程安全的餓漢模式和懶漢模式

單例模式

解決的問題:保證一個類在記憶體中的對象唯一性.

比如:多程式讀取一個配置檔案時,建議配置檔案封裝成對象。會友善操作其中資料,又要保證多個程式讀到的是同一個配置檔案對象,

就需要該配置檔案對象在記憶體中是唯一的。

如何保證對象唯一性呢?

思想:

1,不讓其他程式建立該類對象。

2,在本類中建立一個本類對象。

3,對外提供方法,讓其他程式擷取這個對象。

步驟:

1,因為建立對象都需要構造函數初始化,隻要将本類中的構造函數私有化,其他程式就無法再建立該類對象;

2,就在類中建立一個私有并靜态的本類的對象;

3,定義一個方法,傳回該對象,讓其他程式可以通過方法就得到本類對象。(作用:可控)

代碼展現:

1,私有化構造函數;

2,建立私有并靜态的本類對象;

3,定義公有并靜态的方法,傳回該對象。

餓漢模式:

class Single{
private Single(){} //私有化構造函數。
private static Single s = new Single(); //建立私有并靜态的本類對象。
public static Single getInstance(){ //定義公有并靜态的方法,傳回該對象。
return s;
}
}
           

//懶漢式:延遲加載方式。使用到的時候才回去初始化該對象

class Single2{
private Single2(){}
private static Single2 s = null;
public static Single2 getInstance(){
if(s==null)
s = new Single2();
return s;
}
}
           

在多線程模式中,考慮到性能和線程安全問題,我們一般會選擇下面兩種比較經典的單例模式,在性能提高的同時,又保證了線程的安全.

1.static inner Class

2.dubble check instance

(餓漢模式)static inner Class-内部靜态類的形式

public class Singletion {
	
	private static class InnerSingletion {
		private static Singletion single = new Singletion();
	}
	
	public static Singletion getInstance(){
		return InnerSingletion.single;
	}
	
}
           

(懶漢模式) dubble check instance-為確定線程安全,需要兩次check

public class DubbleSingleton {

	private static DubbleSingleton ds;
	
	public  static DubbleSingleton getDs(){
		if(ds == null){
			try {
				//模拟初始化對象的準備時間...
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized (DubbleSingleton.class) {
				if(ds == null){
					ds = new DubbleSingleton();
				}
			}
		}
		return ds;
	}
	
	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DubbleSingleton.getDs().hashCode());
			}
		},"t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DubbleSingleton.getDs().hashCode());
			}
		},"t2");
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DubbleSingleton.getDs().hashCode());
			}
		},"t3");
		
		t1.start();
		t2.start();
		t3.start();
	}
	
}
           

輸出結果:

792363696
792363696
792363696