源博客:https://www.cnblogs.com/hupp/p/4487521.html
- 單線程環(huán)境使用
package test;
/**
* @author xiaoping
*
*/
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
注解:Singleton的靜態(tài)屬性instance中婉支,只有instance為null的時候才創(chuàng)建一個實例,構(gòu)造函數(shù)私有,確保每次都只創(chuàng)建一個,避免重復(fù)創(chuàng)建。
缺點:只在單線程的情況下正常運行异雁,在多線程的情況下,就會出問題僧须。例如:當(dāng)兩個線程同時運行到判斷instance是否為空的if語句纲刀,并且instance確實沒有創(chuàng)建好時,那么兩個線程都會創(chuàng)建一個實例担平。
- 多線程的情況可以用示绊。(懶漢式,不好)
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
注解:在解法一的基礎(chǔ)上加上了同步鎖暂论,使得在多線程的情況下可以用面褐。例如:當(dāng)兩個線程同時想創(chuàng)建實例,由于在一個時刻只有一個線程能得到同步鎖取胎,當(dāng)?shù)谝粋€線程加上鎖以后展哭,第二個線程只能等待。第一個線程發(fā)現(xiàn)實例沒有創(chuàng)建闻蛀,創(chuàng)建之匪傍。第一個線程釋放同步鎖,第二個線程才可以加上同步鎖循榆,執(zhí)行下面的代碼析恢。由于第一個線程已經(jīng)創(chuàng)建了實例,所以第二個線程不需要創(chuàng)建實例秧饮。保證在多線程的環(huán)境下也只有一個實例映挂。
缺點:每次通過getInstance方法得到singleton實例的時候都有一個試圖去獲取同步鎖的過程。而眾所周知盗尸,加鎖是很耗時的柑船。能避免則避免。
- 加同步鎖時泼各,前后兩次判斷實例是否存在(可行)
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
注解:只有當(dāng)instance為null時鞍时,需要獲取同步鎖,創(chuàng)建一次實例扣蜻。當(dāng)實例被創(chuàng)建逆巍,則無需試圖加鎖。
缺點:用雙重if判斷莽使,復(fù)雜锐极,容易出錯。
- 餓漢式(建議使用)
public class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
注解:初試化靜態(tài)的instance創(chuàng)建一次芳肌。如果我們在Singleton類里面寫一個靜態(tài)的方法不需要創(chuàng)建實例灵再,它仍然會早早的創(chuàng)建一次實例肋层。而降低內(nèi)存的使用率。
缺點:沒有l(wèi)azy loading的效果翎迁,從而降低內(nèi)存的使用率栋猖。
- 靜態(tài)內(nèi)部內(nèi)。(建議使用)
public class Singleton {
private Singleton(){}
private static class SingletonHolder{
private final static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
注解:定義一個私有的內(nèi)部類汪榔,在第一次用這個嵌套類時蒲拉,會創(chuàng)建一個實例。而類型為SingletonHolder的類揍异,只有在Singleton.getInstance()中調(diào)用全陨,由于私有的屬性,他人無法使用SingleHolder衷掷,不調(diào)用Singleton.getInstance()就不會創(chuàng)建實例。
優(yōu)點:達到了lazy loading的效果柿菩,即按需創(chuàng)建實例戚嗅。