簡單,又不簡單,看看便知道。建議采用demo-4。
demo-1 懶漢式(synchronized)
/**
public class Singleton {
/**
* 定義一個變量來存儲創建好的類實例
*/
private static Singleton uniqueInstance = null;
/**
* 私有化構造方法,好在內部控制創建實例的數目
*/
private Singleton(){
//
}
/**
* 定義一個方法來為客戶端提供類實例
* @return 一個Singleton的實例
*/
public static synchronized Singleton getInstance(){
//判斷存儲實例的變量是否有值
if(uniqueInstance == null){
//如果沒有,就創建一個類實例,並把值賦值給存儲類實例的變量
uniqueInstance = new Singleton();
}
//如果有值,那就直接使用
return uniqueInstance;
}
/**
* 示意方法,單例可以有自己的操作
*/
public void singletonOperation(){
//功能處理
}
/**
* 示意屬性,單例可以有自己的屬性
*/
private String singletonData;
/**
* 示意方法,讓外部通過這些方法來訪問屬性的值
* @return 屬性的值
*/
public String getSingletonData(){
return singletonData;
}
}
demo-2 懶漢式 (雙重檢查加鎖)
public class Singleton {
/**
* 對保存實例的變量添加volatile的修飾
*/
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
//先檢查實例是否存在,如果不存在才進入下面的同步塊
if(instance == null){
//同步塊,線程安全的創建實例
synchronized(Singleton.class){
//再次檢查實例是否存在,如果不存在才真的創建實例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
demo-3 餓流式
public class Singleton {
//4:定義一個靜態變量來存儲創建好的類實例
//直接在這里創建類實例,只會創建一次
private static Singleton instance = new Singleton();
//1:私有化構造方法,好在內部控制創建實例的數目
private Singleton(){
}
//2:定義一個方法來為客戶端提供類實例
//3:這個方法需要定義成類方法,也就是要加static
//這個方法里面就不需要控制代碼了
public static Singleton getInstance(){
//5:直接使用已經創建好的實例
return instance;
}
}
demo-4 內部類
public class Singleton {
/**
* 類級的內部類,也就是靜態的成員式內部類,該內部類的實例與外部類的實例
* 沒有綁定關系,而且只有被調用到才會裝載,從而實現了延遲加載
*/
private static class SingletonHolder{
/**
* 靜態初始化器,由JVM來保證線程安全
*/
private static Singleton instance = new Singleton();
}
/**
* 私有化構造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
備注:
1. 全局共享,獨一份;
2. 構造函數不暴露(如果暴露便不能保證一份),自己負責自己的構造;
3. 懶漢式:Lazy load,用到才加載,非線程安全。如何保證線程安全呢:
(1) synchronized getInstance()。見demo-1
(2)雙重檢查加鎖。見demo-2。
4. 餓漢式:一開始就申請好,浪費了點資源,但其線程安全。 見demo-3。
5. 內部類:
(1)改成內部類,由JVM保證線程安全性。見demo-4。
參考: