我理解的單例設計模式
阿新 • • 發佈:2018-03-06
單例模式 singleton 單例模式我們在開發中經常用到,但是我們可能熟知一種單例模式,但是單例模式也有好多種,現在就對幾種單例模式做個比較,明白其中的優缺點:
- 單例代碼:“餓漢式”,也就是當類加載進來的時候就創建實例,但是這種方式比較消耗資源。(單例模式的第一個版本)
public class Singleton{ private static Singleton single=new Singleton(); private Singleton(){ System.out.println("生成一個Singleton實例"); } public static Singleton getInstance(){ return single; } }
2.測試代碼
public class SingletonTest{ public static void main(String[] args){ System.out.println("Start..."); Singleton single1=Singleton.getInstance(); Singleton single2=Singleton.getInstance(); if(single1==single2){ System.out.println("obj1 和 obj2 是相同的實例。"); }else{ System.out.println("obj1 和 obj2 是不同的實例。"); } System.out.println("End..."); } }
3.測試結果
Start...
生成一個Singleton實例
obj1 和 obj2 是相同的實例。
End...
- 不是嚴格的Singleton模式的例子:“懶漢式”:單線程下可以,多線程下存在線程安全問題。(單例模式的第二個版本), 這段代碼如果是在單線程中是沒有什麽問題的,但是因為沒有鎖的機制,在多線程中就會有問題,當同一時間有兩個或者兩個以上線程進入getInstance()方法時,因為剛開始single都是null , 幾個線程都同時滿足if(single==null) 這個條件,就會同時new Singleton() 這個對象
public class Singleton{ private static Singleton single=null; private Singleton(){ System.out.println("生成一個Singleton實例"); } public static Singleton getInstance(){ if(single==null){ single=new Singleton(); } return single; } }
5.不是嚴格單例模式測試代碼
public class SingletonThread implements Runnable {
private Set<Singleton> set=new HashSet<Singleton>();
@Override
public void run() {
Singleton single=Singleton.getInstance();
set.add(single);
System.out.println("Set的大小為:"+set.size()+","+set);
}
}
測試類Main方法
public class SingleTest {
public static void main(String[] args) {
SingletonThread t=new SingletonThread();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
6.測試結果:會看到會有多個“生成一個Singleton實例”,說明調用了5次 new Singleton()方法。
7.如果使用第一種方法的話:只會有一個“生成一個Singleton實例 ”,說明只調用了一次 new Singleton() 方法。
8.為了解決第二種多線程安全問題,采用對函數進行同步的方式,但是也比較浪費資源,因為每次都要進行同步檢查,而實際真正需要檢查的只是第一次。(單例模式的第三個版本)
public class Singleton{
private static Singleton single=null;
private Singleton(){
System.out.println("生成一個Singleton實例");
}
public static synchronized Singleton getInstance(){
if(single==null){
single=new Singleton();
}
return single;
}
}
運行結果:
9.(單例模式的第四個版本)既解決了“懶漢式”多線程的安全問題,又解決了浪費資源的現象。
public class Singleton{
private static Singleton single;
private Singleton(){
System.out.println("生成一個Singleton實例");
}
public static Singleton getInstance(){
if(single==null){
synchronized(Singleton.class) {
if(single==null) {
single=new Singleton();
}
}
}
return single;
}
}
運行結果:
10.單例模式優缺點總結:
優點:客戶端使用單例模式的實例的時候,只需要調用一個單一的方法就可以得到一個唯一的實例,有利於節省資源。
缺點:首先單例模式很難實現實例化,這就導致采用單例模式的類很難被持久化,當然也很難通過網絡進行傳輸;其次,由於單例采用靜態方法,無法再繼承結構中使用。
我理解的單例設計模式