線程安全的單例模式的幾種實(shí)現(xiàn)方法分享
1、餓漢式單例
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return INSTANCE;
}
}
2、借助內(nèi)部類
屬于懶漢式單例,因?yàn)镴ava機(jī)制規(guī)定,內(nèi)部類SingletonHolder只有在getInstance()方法第一次調(diào)用的時(shí)候才會(huì)被加載(實(shí)現(xiàn)了lazy),而且其加載過程是線程安全的。內(nèi)部類加載的時(shí)候?qū)嵗淮蝘nstance。
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
3、普通加鎖解決
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
雖然解決了線程安全問題,但是每個(gè)線程調(diào)用getInstance都要加鎖,我們想要只在第一次調(diào)用getInstance時(shí)加鎖,請(qǐng)看下面的雙重檢測方案
4、雙重檢測,但要注意寫法
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
Singleton temp = instance;
if(temp == null) {
temp = new Singleton();
instance = temp
}
}
}
return instance;
}
}
由于指令重排序問題,所以不可以直接寫成下面這樣:
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
但是如果instance實(shí)例變量用volatile修飾就可以了,volatile修飾的話就可以確保instance = new Singleton();對(duì)應(yīng)的指令不會(huì)重排序,如下的單例代碼也是線程安全的:
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
相關(guān)文章
淺談在Java中使用Callable、Future進(jìn)行并行編程
這篇文章主要介紹了淺談在Java中使用Callable、Future進(jìn)行并行編程,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12vue+springboot項(xiàng)目上傳部署tomcat的方法實(shí)現(xiàn)
本文主要介紹了vue+springboot項(xiàng)目上傳部署tomcat的方法實(shí)現(xiàn),包括環(huán)境準(zhǔn)備、配置調(diào)整以及部署步驟,文中通過圖文及示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程
這篇文章主要為大家詳細(xì)介紹了Eclipse下基于Java的OpenCV開發(fā)環(huán)境配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07SpringCloud_Eureka服務(wù)注冊(cè)與發(fā)現(xiàn)基礎(chǔ)及構(gòu)建步驟
Eureka服務(wù)注冊(cè)中心,主要用于提供服務(wù)注冊(cè)功能,當(dāng)微服務(wù)啟動(dòng)時(shí),會(huì)將自己的服務(wù)注冊(cè)到Eureka Server,這篇文章主要介紹了SpringCloud中Eureka的配置及詳細(xì)使用,需要的朋友可以參考下2023-01-01shrio中hashedCredentialsMatcher密碼匹配示例詳解
shrio是一個(gè)輕量級(jí)權(quán)限管理框架,密碼的匹配由框架內(nèi)部完成。密碼是否匹配由接口CredentialsMatcher定義實(shí)現(xiàn)類完成,CredentialsMatcher實(shí)現(xiàn)類有SimpleCredentialsMatcher和HashedCredentialsMatcher兩個(gè)2021-10-10