Java實現(xiàn)單例模式的五種方法介紹
餓漢式
立即加載
防止new對象,構造私有,寫一個公共的方法返回對象
占用空間,線程安全
public class Singleton {
/**
* 私有構造
*/
private Singleton(){
System.out.println("構造函數(shù)Singleton");
}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
}
懶漢式
延遲加載
占用空間小,效率有問題,線程不安全
public class Singleton {
/**
* 私有構造
*/
private Singleton(){
System.out.println("構造函數(shù)Singleton");
}
private static Singleton singleton = null;
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
解決線程安全問題
在方法上加synchronized同步鎖或是用同步代碼塊對類加同步鎖,此種方式雖然解決了多個實例對象問題,但是該方式運行效率卻很低下,下一個線程想要獲取對象,就必須等待上一個線程釋放鎖之后,才可以繼續(xù)運行。
鎖太大
public class Singleton {
/**
* 私有構造
*/
private Singleton(){
System.out.println("構造函數(shù)Singleton");
}
private static Singleton singleton = null;
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
雙重檢查鎖
提高同步鎖的效率
使用雙重檢查鎖進一步做了優(yōu)化,可以避免整個方法被鎖,只對需要鎖的代碼部分加鎖,可以提高執(zhí)行效率。
第一個if判斷
第一個線程進來new了Singleton,那么singleton就有值,第二個線程進來,那么進行第一個if判斷,不為null,直接返回,不用再去new了,提升了效率
第二個if判斷
兩個線程同時進來,在synchronized,第一個線程進入,另一個線程等待,第一個線程new Singleton,然后返回,另一個線程發(fā)現(xiàn)了第一個線程走了,進入synchronized,如果不進行if判斷,那么還會new Singleton,導致線程不安全
public class Singleton {
/**
* 私有構造
*/
private Singleton(){
System.out.println("構造函數(shù)Singleton");
}
private static Singleton singleton = null;
public static synchronized Singleton getInstance(){
if (singleton == null){ //這個檢查是提高效率的
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton(); //這個檢查是防止線程安全的
}
}
}
return singleton;
}
}
靜態(tài)內(nèi)部類
這種方式引入了一個內(nèi)部靜態(tài)類(static class),靜態(tài)內(nèi)部類只有在調(diào)用時才會加載,它保證了Singleton 實例的延遲初始化,又保證了實例的唯一性。它把singleton 的實例化操作放到一個靜態(tài)內(nèi)部類中,在第一次調(diào)用getInstance() 方法時,JVM才會去加載InnerObject類,同時初始化singleton 實例,所以能讓getInstance() 方法線程安全。
特點是:即能延遲加載,也能保證線程安全。
靜態(tài)內(nèi)部類雖然保證了單例在多線程并發(fā)下的線程安全性,但是在遇到序列化對象時,默認的方式運行得到的結果就是多例的。
public class Singleton {
/**
* 私有構造
*/
private Singleton(){
}
private static class InnerObject{
private static Singleton singleton = new Singleton();
}
public static synchronized Singleton getInstance(){
return InnerObject.singleton;
}
}
內(nèi)部枚舉類實現(xiàn)
防止反射和反序列化攻擊
實上,通過Java反射機制是能夠實例化構造方法為private的類的。這也就是我們現(xiàn)在需要引入的枚舉單例模式。
public class SingletonFactory {
/**
* 私有構造
*/
private enum EnumSingleton{
SINGLETON;
private Singleton6 singleton;
//枚舉類的構造方法在類加載是被實例化
private EnumSingleton(){
singleton = new Singleton6();
}
public Singleton6 getInstance(){
return singleton;
}
}
public static Singleton6 getInstance(){
return EnumSingleton.SINGLETON.getInstance();
}
}
class Singleton6{
public Singleton6(){
}
}
到此這篇關于Java實現(xiàn)單例模式的五種方法介紹的文章就介紹到這了,更多相關Java單例模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java實戰(zhàn)之小米交易商城系統(tǒng)的實現(xiàn)
這篇文章將利用Java實現(xiàn)小米交易商城系統(tǒng),文中采用的技術有:JSP?、Spring、SpringMVC、MyBatis等,感興趣的小伙伴可以跟隨小編一起學習一下2022-04-04
mybatis-plus查詢無數(shù)據(jù)問題及解決
這篇文章主要介紹了mybatis-plus查詢無數(shù)據(jù)問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
Lock、Condition實現(xiàn)簡單的生產(chǎn)者消費者模式示例
這篇文章主要介紹了Lock、Condition實現(xiàn)簡單的生產(chǎn)者消費者模式示例,需要的朋友可以參考下2014-04-04

