Java中單例(Singleton)模式是一種廣泛使用的設(shè)計(jì)模式。單例模式的主要作用是保證在Java程序中,某個(gè)類只有一個(gè)實(shí)例存在喇闸。一些管理器和控制器常被設(shè)計(jì)成單例模式。
1询件,餓漢式---在類初始化時(shí)燃乍,已經(jīng)自行實(shí)例化
public class Person{
private static final Person person=new Person();
//私有構(gòu)造函數(shù),外界無(wú)法使用
private Person(){
}
//提供一個(gè)方法宛琅,獲得對(duì)象
public static Person getPerson(){
return person;
}
}
注:餓漢式在類創(chuàng)建的同時(shí)就已經(jīng)創(chuàng)建好一個(gè)靜態(tài)的對(duì)象供系統(tǒng)使用刻蟹,以后不再改變,所以天生是線程安全的夯秃。
缺點(diǎn):餓漢式在類創(chuàng)建的同時(shí)就實(shí)例化一個(gè)靜態(tài)對(duì)象出來(lái)座咆,不管之后會(huì)不會(huì)使用這個(gè)單例痢艺,都會(huì)占據(jù)一定的內(nèi)存仓洼,但是相應(yīng)的,在第一次調(diào)用時(shí)速度也會(huì)更快堤舒,因?yàn)槠滟Y源已經(jīng)初始化完成色建,
2,懶漢式(線程不安全)--顧名思義舌缤,什么時(shí)候用箕戳,什么時(shí)候創(chuàng)建
public class Person{
private static Person person;
//私有構(gòu)造函數(shù)
private Person(){
}
public static Person getPerson(){
if(person==null){
person=new Person();
}
return person;
}
3某残,懶漢式(線程安全)
public class Person{
private static Person person=null;
private Person(){
}
//添加 synchronized 同步鎖
public static synchronized Person getPerson(){
if(person==null){
person=new Person();
}
return person;
}
}
注:在2.懶漢式基礎(chǔ)上,添加同步鎖陵吸,使得在多線程中可以使用玻墅。例如:當(dāng)兩個(gè)線程同時(shí)想創(chuàng)建實(shí)例,由于同一時(shí)刻只有一個(gè)線程能夠得到同步鎖壮虫,當(dāng)?shù)谝粋€(gè)線程得到后第二個(gè)線程只能等待澳厢,如果沒(méi)有創(chuàng)建該實(shí)例,就會(huì)創(chuàng)建囚似。第一個(gè)線程釋放同步鎖以后第二個(gè)線程才能加上同步鎖剩拢,執(zhí)行內(nèi)部代碼,由于第一個(gè)線程已經(jīng)創(chuàng)建了實(shí)例饶唤,所以第二個(gè)線程不需要重復(fù)創(chuàng)建徐伐。保證了多線程環(huán)境下也只有一個(gè)實(shí)例。
缺點(diǎn):每次通過(guò) getPerson() 方法得到實(shí)例的時(shí)候都會(huì)有一個(gè)試圖去獲取同步鎖的過(guò)程募狂,然而加鎖是很耗時(shí)的办素,所以能避免就避免。
4祸穷,懶漢式(雙重鎖摸屠,線程安全)
public class Person{
private static Person person=null;
private Person(){
}
public static Person getPerson(){
if(person==null){
synchronized(Person.class){
if(person==null){
person=new Person();
}
}
}
return person;
}
}
注:只有在person==null的時(shí)候,才需要獲取同步鎖粱哼,創(chuàng)建一次實(shí)例季二。當(dāng)實(shí)例被創(chuàng)建,則無(wú)需試圖加同步鎖揭措,避免3中的問(wèn)題胯舷。
缺點(diǎn):使用雙重if判斷,復(fù)雜绊含,容易出錯(cuò)桑嘶。
5,靜態(tài)內(nèi)部類(建議使用)
public class Person{
private Person(){
}
/**
* 靜態(tài)初始化器躬充,由JVM來(lái)保證線程安全
*/
private static class SingletonPerson{
private final static Person person=new Person();
}
public static Person getPerson(){
return SingletonPerson.person;
}
}
注:上面的SingletonPerson
內(nèi)部類的實(shí)例與外部類的實(shí)例沒(méi)有綁定關(guān)系逃顶,只有被調(diào)用才會(huì)被加載,也就是實(shí)現(xiàn)了延時(shí)加載充甚。即按需創(chuàng)建實(shí)例以政。