單例模式:確保某一個(gè)類只有一個(gè)實(shí)例恰矩,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例仿便。
使用場(chǎng)景:
1.復(fù)雜對(duì)象迄沫,避免對(duì)象創(chuàng)建過多消耗系統(tǒng)資源稻扬。
2.某種類型的對(duì)象只應(yīng)該有且只有一個(gè)。
單例模式的寫法:
1.餓漢式
/**
* 餓漢式
*/
public class Singleton1 {
private static final Singleton1 instance = new Singleton1();
private Singleton1(){
}
private static Singleton1 getInstance(){
return instance;
}
}
優(yōu)點(diǎn):在類裝載的時(shí)候就完成實(shí)例化羊瘩,避免了線程同步的問題泰佳。
缺點(diǎn):浪費(fèi)內(nèi)存。
2.懶漢式
/**
* 懶漢式
*/
public class Singleton2 {
private static Singleton2 instance= null;
private Singleton2(){
}
private static synchronized Singleton2 getInsatance(){
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
優(yōu)點(diǎn):實(shí)現(xiàn)延時(shí)加載和線程同步尘吗。
缺點(diǎn):效率太低逝她,每次調(diào)用getInstance方法都需要同步。
懶漢式另一種實(shí)現(xiàn)方式睬捶,鎖實(shí)例的代碼塊不鎖方法
/**
* 懶漢式
*/
public class Singleton2 {
private static Singleton2 instance= null;
private Singleton2(){
}
private static Singleton2 getInsatance(){
if (instance == null) {
synchronized (Singleton2.class){
instance = new Singleton2();
}
}
return instance;
}
}
這種方式并不能真正實(shí)現(xiàn)線程同步黔宛,當(dāng)多個(gè)線程同時(shí)進(jìn)入 if (instance == null) 的判斷,那么就會(huì)出現(xiàn)多個(gè)實(shí)例擒贸。
3.雙重檢查模式
/**
* 雙重檢查模式
*/
public class Singleton3 {
/**
* volatile 關(guān)鍵字的作用:
* 首先這里有兩個(gè)東西 工作內(nèi)存和主內(nèi)存臀晃。工作內(nèi)存是線程的獨(dú)有的觉渴,而主內(nèi)存是全局的多個(gè)線程中主內(nèi)存內(nèi)容才最終有效。
* 而多個(gè)工作內(nèi)存與主內(nèi)存之間 jmm是提供機(jī)制保證一致性的徽惋,什么時(shí)候保證呢疆拘?線程空閑的時(shí)候(畢竟線程一致占據(jù)CPU也
* 沒法去更新),也就是在線程讓出CPU后jmm會(huì)嘗試將主內(nèi)存的內(nèi)容刷新到工作內(nèi)存中寂曹。
* 那volatile是怎么實(shí)現(xiàn)的哎迄?很簡(jiǎn)單 工作內(nèi)存中不保留volatile變量的副本,每個(gè)線程對(duì)volatile變量的訪問直接訪問主內(nèi)存隆圆。
*/
private static volatile Singleton3 instance = null;
private Singleton3(){}
public static Singleton3 getInstance(){
if (instance == null) {
synchronized (Singleton3.class){
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
雙重檢查模式是使用最多的單例模式漱挚,資源利用率高,第一次執(zhí)行g(shù)etInstance時(shí)單例對(duì)象才會(huì)被實(shí)例化渺氧,效率高旨涝。高并發(fā)的情況下有一定缺陷,但是發(fā)生概率比較小侣背。
4.靜態(tài)內(nèi)部類模式
/**
* 靜態(tài)內(nèi)部類單例模式
*/
public class Singleton4 {
private Singleton4(){}
private static class singletonHolder{
private static final Singleton4 instance = new Singleton4();
}
private static Singleton4 getInstance(){
return singletonHolder.instance;
}
}
第一次加載Singleton4類時(shí)并不會(huì)初始化instance白华,只有在第一次調(diào)用getInstance方法時(shí)才會(huì)實(shí)例instance。這種方式不僅能夠保證線程安全贩耐,也能夠保證單例對(duì)象的唯一性弧腥,同時(shí)實(shí)現(xiàn)了延時(shí)加載。所以這種方式是推薦使用的單例模式潮太。