一般我們在項目開發中有時候常會遇到數據庫的連接(不使用框架),我們常會在dao類中寫一些通用的方法以供後面使用。一般的做法是哪裏需要操作數據庫的方法哪裏就會創建一個對象,然後再引用對象裏面的操作方法,這樣做的不好的地方就是創建的對象比較多,比較消耗內存,降低程序效率,而我們完全可以只創建一個對象,然後哪裏需要哪裏就直接用,無需重新創建,這就是單例模式。
一、懶漢式單例(線程安全,推薦使用)
懶漢式單例顧名思義,它是驅動型的單例模式。當某個用戶(線程)需要某個對象實例時纔會去創建,而再未被需要之前不會主動去創建。在一些需要自己創建的工具類時,可以將其定義爲一個單例類,因爲在整個項目當中工具類只需要創建一次。
優缺點: 類加載較塊,但獲取對象較慢(需要先創建,僅針對第一次實例化),需要進行線程同步,保證線程安全。
注意: 在這個寫法中用到了兩次if(singleton == null)判斷語句,因爲當一個線程執行完if(singleton == null)還未執行下面的語句時,有另一個線程也執行完if語句,然後再執行下面的,此時會產生多個對象,線程不安全。但是當再加一個判斷語句時,當某一個線程已經創建了該對象時,另一個線程在進行執行第二個if語句時直接返回false,從而不會創建多餘的對象。
public class Singleton {//簡單實現一個單例模型
private static Singleton singleton ;
private static Object object=new Object();
/*私有化構造函數,使得在外部不能創建對象,這是實現單例模式的關鍵*/
private Singleton(){}
/*獲取object對象鎖,進行線程同步,在前一個線程未釋放該鎖時,其他線程需等待*/
public static Singleton geiInstance(){
if(util==null){
synchronized (object){
if(util==null){
util=new Singleton();
}
}
}
return util;
}
public static void main(String[] args) {
Singleton singleton1 = Singleton.geiInstance();
Singleton singleton2 = Singleton.geiInstance();
System.out.println(singleton 1==singleton 2);
}
}
//輸出:true
二、餓漢式單例
餓漢式單例即主動型單例模式,不管用戶用不用得到,它都會提前實例化對象等待用戶調用。
優缺點: 在類加載時就已經實例化,因此類加載較慢,但獲取對象比較快,不存在線程安不安全的問題。
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getSingleton(){
return singleton;
}
public static void main(String[] args) {
Singleton util1= Singleton.getSingleton();
Singleton util2= Singleton.getSingleton();
System.out.println(util1==util2);
}
}
//輸出:true