1、懶漢模式:
public class Singleton {
private static Singleton mSingleton;
private Singleton() {
}
/**
*
* 線程安全
*
* @return
*/
public static synchronized Singleton getInstance() {
if (mSingleton == null) {
mSingleton = new Singleton();
}
return mSingleton;
}
/**
* 線程不安全
*
* @return
*/
/*public static Singleton getInstance() {
if (mSingleton == null) {
mSingleton = new Singleton();
}
return mSingleton;
}*/
}
特點(diǎn):
優(yōu)點(diǎn):?jiǎn)卫挥性谑褂玫臅r(shí)候才會(huì)被實(shí)例化,在一定程序上節(jié)約了資源
缺點(diǎn):第一次加載時(shí)需要及時(shí)進(jìn)行實(shí)例化,反應(yīng)稍慢,最大的問題是每次調(diào)用getInstance都進(jìn)行同步,行成不必要的同步開銷。這種模式一般不建議使用。
2、餓漢模式:
public class Singleton {
private static final Singleton mSingleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return mSingleton;
}
}
特點(diǎn):
優(yōu)點(diǎn):沒有加鎖,執(zhí)行效率會(huì)提高。
缺點(diǎn):類加載時(shí)就初始化,浪費(fèi)內(nèi)存。
3、雙重檢查加載
public class Singleton {
private volatile static Singleton mSingleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (mSingleton == null) {
synchronized (Singleton.class) {
if (mSingleton == null) {
mSingleton = new Singleton();
}
}
}
return mSingleton;
}
}
特點(diǎn):
優(yōu)點(diǎn):資源利用率高,第一次執(zhí)行g(shù)etInstance時(shí)單例對(duì)象才會(huì)被實(shí)例化,效率高
缺點(diǎn):第一次加載時(shí)反應(yīng)稍慢,而且volatile或多或少會(huì)影響到性能。
4、靜態(tài)內(nèi)部類
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.mSingleton;
}
private static class SingletonHolder {
private static final Singleton mSingleton = new Singleton();
}
}
特點(diǎn):
當(dāng)?shù)谝淮渭虞dSingleton類時(shí)并不會(huì)初始化mSingleton,只能第一次調(diào)用getInstance方法時(shí)才會(huì)導(dǎo)致mSingleton被初始化。因此,第一次調(diào)用getInstance方法會(huì)導(dǎo)致虛擬機(jī)加載SingletonHolder類,這種方式不僅能確保安全,也能保證單例對(duì)象的唯一性,同時(shí)也延遲了單例的實(shí)例化。推薦性使用該實(shí)現(xiàn)方式;
5、枚舉
public enum SingletonEnum {
SINGLETON;
}
特點(diǎn):
寫法簡(jiǎn)單,線程安全,能杜絕單例對(duì)象在被反序列化的重新生成新的對(duì)象
注意:除了枚舉,上面幾種單例模式如果想杜絕單例對(duì)象在被反序列化的重新生成新的對(duì)象,要實(shí)現(xiàn)Serializable接口
private Object readResolve() throws ObjectStreamException {
return SingletonHolder.mSingleton;
}
6、使用容器實(shí)現(xiàn)單例模式
public class SingletonManager {
private static Map<String, Object> mSingletonManager = new HashMap<String, Object>();
private SingletonManager() {
}
public static void addSingletonToMangager(String key, Object singleton) {
if (!mSingletonManager.containsKey(key)) {
mSingletonManager.put(key, singleton);
}
}
public static Object getSingletonFromManager(String key) {
return mSingletonManager.get(key);
}
}
特點(diǎn):
在程序的初始,將多種單例類型注入到一個(gè)統(tǒng)一的管理類中,在使用時(shí)根據(jù)key獲取對(duì)象對(duì)應(yīng)類型的對(duì)象,這使我們可以管理多種類型的單例,并且使用時(shí)可以通過統(tǒng)一的接口進(jìn)行獲取。
總結(jié)
1、構(gòu)造函數(shù)不對(duì)外開放,private;
2、通過一個(gè)靜態(tài)方法或者枚舉返回單例類對(duì)象;
3、確保單例類的對(duì)象有且只有一個(gè),尤其是在多線程環(huán)境下;
4、確保單例類對(duì)象在反序列化時(shí)不會(huì)重新構(gòu)建對(duì)象。