Java中單例模式是一種常見(jiàn)的設(shè)計(jì)模式
三種單例模式?
懶漢式單例家浇、餓漢式單例、登記式單例碴裙。
單例模式有以下特點(diǎn):
? ??????1、單例類只能有一個(gè)實(shí)例点额。
2舔株、單例類必須自己創(chuàng)建自己的唯一實(shí)例。
3还棱、單例類必須給所有其他對(duì)象提供這一實(shí)例载慈。
????單例模式確保某個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例珍手。在計(jì)算機(jī)系統(tǒng)中办铡,線程池、緩存琳要、日志對(duì)象寡具、對(duì)話框、打印機(jī)稚补、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例童叠。這些應(yīng)用都或多或少具有資源管理器的功能。每臺(tái)計(jì)算機(jī)可以有若干個(gè)打印機(jī)课幕,但只能有一個(gè)Printer Spooler厦坛,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)中。每臺(tái)計(jì)算機(jī)可以有若干通信端口乍惊,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口杜秸,以避免一個(gè)通信端口同時(shí)被兩個(gè)請(qǐng)求同時(shí)調(diào)用∪笠铮總之撬碟,選擇單例模式就是為了避免不一致狀態(tài),避免政出多頭凡橱。
一小作、懶漢式單例(面試常問(wèn))
1//懶漢式單例類.在第一次調(diào)用的時(shí)候?qū)嵗约? ?
public class Singleton {
? ? private Singleton() {}
? ? private static Singleton single=null;
? ? //靜態(tài)工廠方法?
? ? public static Singleton getInstance() {
? ? ? ? if (single == null) {
? ? ? ? ? ? single = new Singleton();
? ? ? ? }
? ? ? ? return single;
? ? }
}
Singleton通過(guò)將構(gòu)造方法限定為private避免了類在外部被實(shí)例化,在同一個(gè)虛擬機(jī)范圍內(nèi)稼钩,Singleton的唯一實(shí)例只能通過(guò)getInstance()方法訪問(wèn)顾稀。
(事實(shí)上坝撑,通過(guò)Java反射機(jī)制是能夠?qū)嵗瘶?gòu)造方法為private的類的静秆,那基本上會(huì)使所有的Java單例實(shí)現(xiàn)失效粮揉。此問(wèn)題在此處不做討論,姑且掩耳盜鈴地認(rèn)為反射機(jī)制不存在抚笔。)
但是以上懶漢式單例的實(shí)現(xiàn)沒(méi)有考慮線程安全問(wèn)題扶认,它是線程不安全的,并發(fā)環(huán)境下很可能出現(xiàn)多個(gè)Singleton實(shí)例殊橙,要實(shí)現(xiàn)線程安全辐宾,有以下三種方式,都是對(duì)getInstance這個(gè)方法改造膨蛮,保證了懶漢式單例的線程安全叠纹,如果你第一次接觸單例模式,對(duì)線程安全不是很了解敞葛,可以先跳過(guò)下面這三小條誉察,去看餓漢式單例,等看完后面再回頭考慮線程安全的問(wèn)題:
1惹谐、在getInstance方法上加同步(性能較差)
public static synchronized Singleton getInstance() {
? ? ? ? if (single == null) {
? ? ? ? ? ? single = new Singleton();
? ? ? ? }
? ? ? ? return single;
}
2持偏、雙重檢查鎖定(DCL 雙檢查鎖機(jī)制)推薦
public static Singleton getInstance() {
? ? ? ? if (singleton == null) {
? ? ? ? ? ? synchronized (Singleton.class) {
? ? ? ? ? ? ? if (singleton == null) {
? ? ? ? ? ? ? ? ? singleton = new Singleton();
? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return singleton;
? ? }
3、靜態(tài)內(nèi)部類 推薦
public class Singleton {
? ? private static class LazyHolder {
? ? ? private static final Singleton INSTANCE = new Singleton();
? ? }
? ? private Singleton (){}
? ? public static final Singleton getInstance() {
? ? ? return LazyHolder.INSTANCE;
? ? }
}