Java中單例(Singleton)模式是一種廣泛使用的設計模式。單例模式的主要作用是保證在Java程序中,某個類只有一個實例存在。一些管理器和控制器常被設計成單例模式。
1,餓漢式---在類初始化時,已經自行實例化
public class Person{
private static final Person person=new Person();
//私有構造函數,外界無法使用
private Person(){
}
//提供一個方法,獲得對象
public static Person getPerson(){
return person;
}
}
注:餓漢式在類創建的同時就已經創建好一個靜態的對象供系統使用,以后不再改變,所以天生是線程安全的。
缺點:餓漢式在類創建的同時就實例化一個靜態對象出來,不管之后會不會使用這個單例,都會占據一定的內存,但是相應的,在第一次調用時速度也會更快,因為其資源已經初始化完成,
2,懶漢式(線程不安全)--顧名思義,什么時候用,什么時候創建
public class Person{
private static Person person;
//私有構造函數
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.懶漢式基礎上,添加同步鎖,使得在多線程中可以使用。例如:當兩個線程同時想創建實例,由于同一時刻只有一個線程能夠得到同步鎖,當第一個線程得到后第二個線程只能等待,如果沒有創建該實例,就會創建。第一個線程釋放同步鎖以后第二個線程才能加上同步鎖,執行內部代碼,由于第一個線程已經創建了實例,所以第二個線程不需要重復創建。保證了多線程環境下也只有一個實例。
缺點:每次通過 getPerson() 方法得到實例的時候都會有一個試圖去獲取同步鎖的過程,然而加鎖是很耗時的,所以能避免就避免。
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的時候,才需要獲取同步鎖,創建一次實例。當實例被創建,則無需試圖加同步鎖,避免3中的問題。
缺點:使用雙重if判斷,復雜,容易出錯。
5,靜態內部類(建議使用)
public class Person{
private Person(){
}
/**
* 靜態初始化器,由JVM來保證線程安全
*/
private static class SingletonPerson{
private final static Person person=new Person();
}
public static Person getPerson(){
return SingletonPerson.person;
}
}
注:上面的SingletonPerson
內部類的實例與外部類的實例沒有綁定關系,只有被調用才會被加載,也就是實現了延時加載。即按需創建實例。