完美解決單例設(shè)計(jì)模式中懶漢式線程安全的問題
首先寫個(gè)單例:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static SingleDemo getInstance(){
if(s == null){
s = new SingleDemo();
}
return s;
}
}
寫個(gè)測(cè)試類:
public class ThreadDemo3 {
public static void main(String[] args) {
SingleDemo s1 = SingleDemo.getInstance();
SingleDemo s2 = SingleDemo.getInstance();
System.out.println(s2 == s2);
}
}
運(yùn)行結(jié)果一直都是true,說明單線程下是沒問題的,下面寫個(gè)多線程來訪問單例
public class ThreadTest implements Runnable {
//存放單例對(duì)象,使用Set是為了不存放重復(fù)元素
public Set<SingleDemo> singles = new HashSet<SingleDemo>();
@Override
public void run() {
//獲取單例
SingleDemo s = SingleDemo.getInstance();
//添加單例
singles.add(s);
}
}
使用多線程并發(fā)訪問單例:
public class ThreadDemo3 {
public static void main(String[] args) {
// SingleDemo s1 = SingleDemo.getInstance();
// SingleDemo s2 = SingleDemo.getInstance();
// System.out.println(s2 == s2);
ThreadTest t = new ThreadTest();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
System.out.println(t.singles);
}
}
運(yùn)行結(jié)果如下:
[com.persagy.thread.SingleDemo@1bc4459, com.persagy.thread.SingleDemo@150bd4d]
或
[com.persagy.thread.SingleDemo@12b6651]
說明有線程并發(fā)訪問安全問題,獲取的不一定都是同一個(gè)實(shí)例
如何解決線程安全問題呢?
當(dāng)然使用同步鎖機(jī)制了啊
下面改進(jìn)單例:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static synchronized SingleDemo getInstance(){
if(s == null){
s = new SingleDemo();
}
return s;
}
}
加入同步函數(shù)后線程安全問題解決了
運(yùn)行多次都是獲取同一個(gè)實(shí)例,不會(huì)出現(xiàn)2個(gè)實(shí)例的情況了
[com.persagy.thread.SingleDemo@12b6651]
但是在多線程并發(fā)訪問的情況下,每個(gè)線程每次獲取實(shí)例都要判斷下鎖,效率比較低,為了提高效率,我加入了雙重判斷的方法,解決了效率的問題
代碼如下:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static SingleDemo getInstance(){
/*如果第一個(gè)線程獲取到了單例的實(shí)例對(duì)象,
* 后面的線程再獲取實(shí)例的時(shí)候不需要進(jìn)入同步代碼塊中了*/
if(s == null){
//同步代碼塊用的鎖是單例的字節(jié)碼文件對(duì)象,且只能用這個(gè)鎖
synchronized(SingleDemo.class){
if(s == null){
s = new SingleDemo();
}
}
}
return s;
}
}
用這種方式解決了懶漢式的線程安全問題,也提高了效率,但是在實(shí)際開發(fā)中還是用餓漢式的比較多,畢竟這個(gè)代碼比較多,比較繁瑣。
以上就是小編為大家?guī)淼耐昝澜鉀Q單例設(shè)計(jì)模式中懶漢式線程安全的問題全部?jī)?nèi)容了,希望大家多多支持腳本之家~
相關(guān)文章
Spring Boot利用Thymeleaf發(fā)送Email的方法教程
spring Boot默認(rèn)就是使用thymeleaf模板引擎的,下面這篇文章主要給大家介紹了關(guān)于在Spring Boot中利用Thymeleaf發(fā)送Email的方法教程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-08-08
JUnit5中的參數(shù)化測(cè)試實(shí)現(xiàn)
參數(shù)化測(cè)試使得我們可以使用不同的參數(shù)運(yùn)行同一個(gè)測(cè)試方法,從而減少我們編寫測(cè)試用例的工作量,本文主要介紹了JUnit5中的參數(shù)化測(cè)試實(shí)現(xiàn),感興趣的可以了解一下2023-05-05
深入Spring Boot實(shí)現(xiàn)對(duì)Fat Jar jsp的支持
這篇文章主要介紹了深入Spring Boot實(shí)現(xiàn)對(duì)Fat Jar jsp的支持,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06
Java 客戶端操作 FastDFS 實(shí)現(xiàn)文件上傳下載替換刪除功能
這篇文章主要介紹了Java 客戶端操作 FastDFS 實(shí)現(xiàn)文件上傳下載替換刪除功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
java面向?qū)ο蟮娜筇匦灾焕^承用法實(shí)例分析
這篇文章主要介紹了java面向?qū)ο蟮娜筇匦灾焕^承用法,結(jié)合實(shí)例形式分析了java面向?qū)ο蟪绦蛟O(shè)計(jì)中繼承的基本原理與具體使用方法,需要的朋友可以參考下2019-11-11
Springboot整合Mybatis傳值的常用方式總結(jié)
今天給大家?guī)淼氖顷P(guān)于Springboot的相關(guān)知識(shí),文章圍繞著Springboot整合Mybatis傳值的常用方式展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06

