單例模式,框架中使用比較多的,開發中較為常用的設計模式。當某種業務需要保證只使用一種例項時,如windows中的工作管理員,永遠只能開啟一個視窗。
1、餓漢式,執行緒安全
public class Singleton{
//建立靜態變數並進行初始化,並且jvm載入時就會進行例項,保證該例項只有一個
//但是對於多執行緒而言,這樣的效率並不高,造成資源的浪費
private static final instance=new Singleton();
private Singleton(){}//將建構函式訪問許可權修改成private,即外部無法通過new進行例項化呼叫
public static Singleton getInstance(){
return instance;
}
}複製程式碼
2、懶漢式,執行緒不安全
//解決了餓漢式的資源浪費的缺點,但是隻能在單執行緒下進行,如果多執行緒下會不安全
public class Singleton{
//建立靜態變數,但不初始化,等待使用時進行初始化
private static Singleton instance=null;
private Singleton(){}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}複製程式碼
3、懶漢式,執行緒安全
//該執行緒安全版本,是在初始化方法上加上同步機制synchronized,是的執行緒安全,但是這種全域性同步,會
使得在多執行緒併發情況下,執行效率不高,故而不推薦
public class Singleton{
private static Singleton instance=null;
private Singleton(){}
private synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}複製程式碼
4、懶漢式,變種,執行緒安全
//該執行緒安全版本,是線上程不安全版本上,使用靜態塊初始化instance例項,通過靜態變數jvm初始化規則
靜態變數/靜態塊-非靜態變數/構造塊-建構函式
public class Singleton{
private static Singleton instance=null;
static {
instance=new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}複製程式碼
5、使用靜態內部類實現,執行緒安全【推薦】
public class Singleton{
private static final class SingletonHolder{
private static final Singleton instance=new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}複製程式碼
6、使用列舉,執行緒安全【推薦】
public class Singleton{
private Singleton(){}
private static Singleton getInstance(){
return SingletonHolder.INSTANCE.getInstance;
}
public enum SingletonHolder{
INSTANCE;
private Singleton instance=null;
SingletonHolder(){
instance=new Singleton();
}
public Singleton getInstance(){
return instance;
}
}
}複製程式碼
7、雙重校驗鎖,執行緒安全【推薦】
public class Singleton{
private static Singleton instance=null;
private Singleton(){}
public static Singleton getInstance(){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}複製程式碼
測試:
public static void main(String[] args) { System.out.println(Singleton.getInstance() == Singleton.getInstance()); System.out.println(Singleton2.getInstance() == Singleton2.getInstance()); System.out.println(Singleton3.getInstance() == Singleton3.getInstance()); System.out.println(Singleton4.getInstance() == Singleton4.getInstance()); System.out.println(Singleton5.getInstance() == Singleton5.getInstance()); System.out.println(Singleton6.INSTANCE == Singleton6.INSTANCE); System.out.println(Singleton7.getInstance() == Singleton7.getInstance()); }
複製程式碼
執行結果: