單例設(shè)計(jì)模式:
某個(gè)類在整個(gè)系統(tǒng)中只能有一個(gè)實(shí)例,對(duì)象可被獲取和使用的代碼模式肴焊。
例如:代表jvm運(yùn)行環(huán))境的Runtime類
單例模式共有的特點(diǎn):1)構(gòu)造器私有化 2) 有個(gè)靜態(tài)變量去保存 3)提供方法區(qū)獲取這個(gè)變量
單例模式分為懶漢式和餓漢式。下面分別介紹懶漢式和餓漢式的幾種寫法。
餓漢式第一種(jdk1.5之前):
public class Singleton1 {
public final static Singleton1 INSTANCE = new Singleton1();
private Singleton1(){
}
}
我們可以直接使用Singleton1.INSTANCE 就可以獲取到這個(gè)單例對(duì)象。
餓漢式第二種(jdk1.5之后)打颤,枚舉:
public enum Singleton2 {
INSTANCE;
}
我們可以直接使用Singleton2.INSTANCE 就可以獲取到這個(gè)單例對(duì)象。枚舉的構(gòu)造器默認(rèn)就為私有的宛畦,所以滿足我們的條件瘸洛。
餓漢式第三種揍移,使用靜態(tài)代碼塊初始化
public class Singleton3 {
public final static Singleton3 INSTANCE;
private String info;
static {
Properties properties = new Properties();
try {
properties.load(Singleton3.class.getClassLoader().getResourceAsStream("info.properties"));
} catch (IOException e) {
e.printStackTrace();
}
String mStr = (String) properties.get("info");
INSTANCE = new Singleton3();
INSTANCE.setInfo(mStr);
}
private Singleton3(){
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return super.toString();
}
}
這種適用于有些變量需要在單例對(duì)象前初始化次和。
餓漢式不涉及到線程安全問(wèn)題,因?yàn)轲I漢式都是在類初始化的時(shí)候初始化類變量那伐,類加載機(jī)制可以避免線程安全問(wèn)題踏施。
懶漢式(延遲加載)
懶漢式第一種(線程不安全):
public class Singleton4 {
private static Singleton4 instance ;
private Singleton4(){
}
public static Singleton4 getInstance(){
if (instance == null){
instance = new Singleton4();
}
return instance;
}
}
調(diào)用類的getInstance方法即可獲取到單例對(duì)象。
懶漢式第二種(線程安全):
public class Singleton5 {
private static Singleton5 instance ;
private Singleton5(){
}
public static Singleton5 getInstance(){
if (instance == null){
synchronized (Singleton5.class){
if (instance == null){
instance = new Singleton5();
}
}
}
return instance;
}
}
為代碼塊加上同步鎖罕邀,來(lái)保證線程安全畅形。
懶漢式第三種(線程安全,使用內(nèi)部類)
/*
* 在內(nèi)部類被加載和初始化時(shí)诉探,才創(chuàng)建INSTANCE實(shí)例對(duì)象
* 靜態(tài)內(nèi)部類不會(huì)自動(dòng)隨著外部類的加載和初始化而初始化日熬,它是要單獨(dú)去加載和初始化的。
* 因?yàn)槭窃趦?nèi)部類加載和初始化時(shí)肾胯,創(chuàng)建的竖席,因此是線程安全的
*/
public class Singleton6 {
private Singleton6(){
}
private static class Inner{
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}
這種方法看起來(lái)代碼更為簡(jiǎn)潔,且利用類加載機(jī)制來(lái)保證了線程的安全敬肚。