中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

購物網(wǎng)站建設(shè)流程百度app客服人工電話

購物網(wǎng)站建設(shè)流程,百度app客服人工電話,建立一個(gè)網(wǎng)址需要多少錢,wordpress 分類目錄 子目錄目錄 [設(shè)計(jì)模式] 單例模式 1. 餓漢模式 2. 懶漢模式 3. 單例模式的線程安全問題 [設(shè)計(jì)模式] 設(shè)計(jì)模式是軟件工程中的一種常見做法, 它可以理解為"模板", 是針對(duì)一些常見的特定場(chǎng)景, 給出的一些比較好的固定的解決方案. 不同語言適用的設(shè)計(jì)模式是不一樣的. 這里…

目錄

[設(shè)計(jì)模式]

單例模式

1. 餓漢模式

2. 懶漢模式

3. 單例模式的線程安全問題


[設(shè)計(jì)模式]

設(shè)計(jì)模式是軟件工程中的一種常見做法, 它可以理解為"模板", 是針對(duì)一些常見的特定場(chǎng)景, 給出的一些比較好的固定的解決方案.?

不同語言適用的設(shè)計(jì)模式是不一樣的. 這里我們接下來要談到的是java中典型的設(shè)計(jì)模式. 而且由于設(shè)計(jì)模式比較適合有一定編程經(jīng)驗(yàn)之后, 再去詳細(xì)學(xué)習(xí), 所以我們本篇文章就只討論幾個(gè)經(jīng)典的java設(shè)計(jì)模式

  • 單例模式

在實(shí)際開發(fā)中, 某個(gè)進(jìn)程中, 我們不希望某個(gè)類有多個(gè)實(shí)例對(duì)象, 希望它有且僅有一個(gè)實(shí)例對(duì)象而且不能再創(chuàng)建出來. --> 這個(gè)時(shí)候我們就可以使用單例模式這樣的設(shè)計(jì)模式. 單例模式有兩種寫法, 一種叫餓漢模式, 一種叫懶漢模式. 下面我們就詳細(xì)討論一下這兩種單例模式的寫法.

1. 餓漢模式

"餓"的意思是"迫切的", 放到代碼中意思就是需要我們?cè)陬惐患虞d的時(shí)候就創(chuàng)建出這個(gè)單例的實(shí)例.?

class Singleton {private static Singleton instance = new Singleton();public static Singleton getInstance() { //獲取Singleton的實(shí)例對(duì)象, 但是每次獲取的都是相同的對(duì)象instance.return instance;}private Singleton() {} //單例模式中最關(guān)鍵的部分: 將構(gòu)造方法設(shè)置為私有. 防止在類外再創(chuàng)建出其他實(shí)例對(duì)象.
}
public class Demo24 {public static void main(String[] args) {Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();//兩次獲取到的對(duì)象應(yīng)該是同一個(gè)對(duì)象. 我們可以在下面驗(yàn)證一下 (== 比較的是兩個(gè)對(duì)象在內(nèi)存中的地址,也就是它們是否指向同一個(gè)實(shí)例對(duì)象)System.out.println(s1 == s2);}
}

?我們可以看到, 餓漢模式中,

(1) static修飾instance, 說明這里的instance是類成員(一個(gè)類只有一份, 隨著類的加載而創(chuàng)建出來)

(2) static修飾的類方法 getInstance() 每次返回的都是同一個(gè)對(duì)象 instance.

(3) 將SIngleton類的構(gòu)造方法設(shè)置為私有, 這就保證了在類外無法通過構(gòu)造方法再創(chuàng)建出新的對(duì)象.

我們通過在main方法中創(chuàng)建兩個(gè)引用s1和s2, 看到s1和s2指向的是同一個(gè)對(duì)象. 這也就代表了Singleton這個(gè)類只有一個(gè)實(shí)例.?

[注]: 上述單例模式只能避免程序員失誤, 調(diào)用了Singleton的構(gòu)造方法創(chuàng)建新對(duì)象;? 而無法避免程序員故意破壞單例模式(比如, 我們可以通過反射的方式拿到構(gòu)造方法).

2. 懶漢模式

我們先通過一個(gè)形象的例子來理解餓漢和懶漢的區(qū)別: 比如我們現(xiàn)在有一個(gè)編輯器, 要打開一個(gè)非常大的文本文檔. (1) 餓漢: 一啟動(dòng), 就把所有的文本內(nèi)容全都讀取到內(nèi)存中, 然后顯示到界面. (2) 懶漢: 先只加載出一部分?jǐn)?shù)據(jù), 隨著用戶的翻頁操作, 再按需加載剩下的內(nèi)容.? 根據(jù)上述表述, 我們可以確定, 懶漢模式一定比餓漢模式加載出來的速度更快, 用戶的體驗(yàn)也就會(huì)更好.?所以, 我們?nèi)粘i_發(fā)中, 很多地方都青睞于使用懶漢模式.

class SingletonLazy {private static SingletonLazy instance = null;public static SingletonLazy getInstance() {if (instance == null) {instance = new SingletonLazy();}return instance;// 如果instance為空,則創(chuàng)建一個(gè)實(shí)例對(duì)象; 如果instance不為空,則直接返回instance}private SingletonLazy() {}
}public class Demo25 {public static void main(String[] args) {SingletonLazy s1 = SingletonLazy.getInstance();SingletonLazy s2 = SingletonLazy.getInstance();System.out.println(s1 == s2);}
}

如上述代碼, 當(dāng)我們首次調(diào)用getInstance時(shí), 由于此時(shí)對(duì)象還沒有創(chuàng)建, instance這個(gè)引用為空, 所以就會(huì)進(jìn)入if分支, 創(chuàng)建出SingletonLazy對(duì)象. 后續(xù)如果再重復(fù)調(diào)用getInstance, 結(jié)果都不會(huì)再創(chuàng)建新的實(shí)例, 而是直接返回instancomen

?我們還是通過在main方法中創(chuàng)建兩個(gè)引用s1和s2, 看到s1和s2指向的是同一個(gè)對(duì)象. 這也就代表了SingletonLazy這個(gè)類只有一個(gè)實(shí)例.

3. 單例模式的線程安全問題

知道了單例模式的兩種寫法之后, 我們現(xiàn)在要判斷: 這兩種寫法是否存在線程安全問題呢? (在多線程環(huán)境下, 多個(gè)線程調(diào)用getInstance, 是否會(huì)出現(xiàn)問題?)

(1) 餓漢模式:

我們可以看到, 餓漢模式的getInstance方法只涉及讀操作, 并沒有涉及任何寫操作. 而我們?cè)诙鄠€(gè)線程同時(shí)修改同一個(gè)變量時(shí), 才容易出現(xiàn)線程安全問題. 所以餓漢模式是線程安全的.

(2) 懶漢模式:

  • 原子操作問題

像這種? 先條件判定, 再修改 的操作, 其實(shí)是典型的線程不安全代碼.?

比如, 我們現(xiàn)在有兩個(gè)線程同時(shí)調(diào)用getInstance方法. 線程t1先執(zhí)行if判斷, 判斷出instance為空. 此時(shí)t2線程插入進(jìn)來了, 執(zhí)行t2線程的if判斷, 那么t2的判斷結(jié)果同樣是空, t2就會(huì)執(zhí)行new SingletonLazy() 創(chuàng)建出一個(gè)新的對(duì)象. 而再切換回t1線程, 由于t1對(duì)instance的判斷也為空, 所以, t1也會(huì)執(zhí)行new SingletonLazy() 創(chuàng)建出一個(gè)新的對(duì)象. 那么這樣的話, Singletonlazy類就被實(shí)例化了兩次. 而單例模式要求類只能被實(shí)例化一次.

([注]: 雖然說后面創(chuàng)建的實(shí)例覆蓋了前面創(chuàng)建的實(shí)例, 前面創(chuàng)建的實(shí)例沒有引用變量引用的話很塊回被銷毀回收, 但是創(chuàng)建實(shí)例對(duì)象這個(gè)過程本身的開銷就很大(比如有的類一個(gè)實(shí)例就要100個(gè)G), 所以我們?nèi)匀徽J(rèn)為這個(gè)代碼是有bug的)

所以, 為了解決上述線程不安全問題, 我們就需要進(jìn)行"加鎖"操作. 將條件判斷和創(chuàng)建操作作為一個(gè)整體加上鎖, 這樣一來, if判斷和new創(chuàng)建操作這個(gè)整體就成了一個(gè)"原子"操作.? 這就保證了某個(gè)線程在順序執(zhí)行這兩個(gè)操作的時(shí)候不會(huì)有別的線程插入進(jìn)來.

class SingletonLazy {private static SingletonLazy instance = null;public static Object locker = new Object(); public static SingletonLazy getInstance() {synchronized(locker) {if (instance == null) {instance = new SingletonLazy();}return instance;// 如果instance為空,則創(chuàng)建一個(gè)實(shí)例對(duì)象; 如果instance不為空,則直接返回instance}}private SingletonLazy() {}
}

試想一下, 上述代碼, 如果已經(jīng)完成了創(chuàng)建對(duì)象的操作之后, 后續(xù)如果再調(diào)用getInstance, 就再也不會(huì)進(jìn)入if分支中去了, 都是簡單的讀操作(return instance). 那么只有讀操作的話, 不加鎖也是線程安全的. 我們知道, 加鎖這個(gè)操作, 對(duì)程序性能的影響還是挺大的.? 所以, 我們只需要在第一次執(zhí)行這個(gè)方法的時(shí)候(沒有創(chuàng)建出對(duì)象的時(shí)候)加鎖即可, 其他時(shí)候再執(zhí)行這個(gè)方法, 都是線程安全的, 不需要加鎖.?

那么, 如何判斷當(dāng)前是不是第一次調(diào)用這個(gè)方法呢? --> 看是否已經(jīng)創(chuàng)建出了實(shí)例對(duì)象, 如果還沒有instance對(duì)象, 那就是第一次調(diào)用, 需要對(duì)里面的判斷-創(chuàng)建對(duì)象 操作 加鎖;? 如果已經(jīng)有了instance對(duì)象, 那就不是第一次調(diào)用, 就不需要加鎖, 直接返回instance.

依據(jù)上述思考, 我們對(duì)代碼做出如下修改:

 public static SingletonLazy getInstance() {if (instance == null) { //外層if: 判斷是否應(yīng)該加鎖synchronized(locker) {if (instance == null) { //內(nèi)層if: 判斷是否要?jiǎng)?chuàng)建對(duì)象instance = new SingletonLazy();}// 如果instance為空,則創(chuàng)建一個(gè)實(shí)例對(duì)象; 如果instance不為空,則直接返回instance}}return instance;}

注意: 這里, 外層if和內(nèi)層if雖然條件恰好是一樣的, 但是作用是完全不同的. 外層的if作用是: 判斷是否要加鎖. 內(nèi)層if的作用是: 判斷是否要?jiǎng)?chuàng)建新的對(duì)象.

  • 指令重排序問題

編譯器在執(zhí)行創(chuàng)建對(duì)象的代碼時(shí), 為了提高性能, 可能會(huì)進(jìn)行"指令重排序"操作.

 instance = new SingletonLazy();

編譯器在執(zhí)行這個(gè)創(chuàng)建對(duì)象代碼的時(shí)候, 會(huì)經(jīng)過如下步驟: (1) 分配內(nèi)存空間.? (2) 執(zhí)行構(gòu)造方法.? (3) 將對(duì)象的內(nèi)存空間地址賦給引用變量.? ?正常來說, 是按照(1) -> (2) -> (3) 的順序執(zhí)行的. 但是編譯器為了優(yōu)化性能, 也可能按照(1) -> (3) -> (2) 的順序執(zhí)行.

 public static SingletonLazy getInstance() {if (instance == null) { //外層if: 判斷是否應(yīng)該加鎖synchronized(locker) {if (instance == null) { //內(nèi)層if: 判斷是否要?jiǎng)?chuàng)建對(duì)象instance = new SingletonLazy();}// 如果instance為空,則創(chuàng)建一個(gè)實(shí)例對(duì)象; 如果instance不為空,則直接返回instance}}return instance;}

那么, 我們?cè)囅? 如果在執(zhí)行完(1) -> (3) 之后, 此時(shí)有別的線程切入, 執(zhí)行if (instance == null) 判定, 那么此時(shí)判定instance就不為空了, 因?yàn)檎Z句指向了內(nèi)存空間(即使這個(gè)內(nèi)存空間里什么都沒有). 判定完instance不為空之后, 就會(huì)直接return instance. 那么如果這個(gè)線程拿到instance之后, 如果再調(diào)用里面的某個(gè)方法. 那么此時(shí)就會(huì)出現(xiàn)錯(cuò)誤!!! (因?yàn)閕nstance指向的內(nèi)存空間是未初始化的).

那么如何解決這個(gè)情況呢? --> volatile. 我們可以在instance前面加上一個(gè)volatile修飾, 告訴系統(tǒng), instance這個(gè)引用是"易變的, 易失的". 那么此時(shí)系統(tǒng)就會(huì)放棄對(duì)new SingletonLazy() 這個(gè)創(chuàng)建對(duì)象操作的優(yōu)化, 按照(1) -> (2) -> (3) 的順序執(zhí)行創(chuàng)建對(duì)象操作.這樣的話, 就不會(huì)出現(xiàn)上述問題了~

加上volatile的代碼最終如下:

class SingletonLazy {private static volatile SingletonLazy instance = null;public static Object locker = new Object();public static SingletonLazy getInstance() {if (instance == null) { //外層if: 判斷是否應(yīng)該加鎖synchronized(locker) {if (instance == null) { //內(nèi)層if: 判斷是否要?jiǎng)?chuàng)建對(duì)象instance = new SingletonLazy();}// 如果instance為空,則創(chuàng)建一個(gè)實(shí)例對(duì)象; 如果instance不為空,則直接返回instance}}return instance;}private SingletonLazy() {}
}

那么這樣一個(gè)單例模式的代碼無論在執(zhí)行效率還是在線程安全上就都沒有任何問題了.

好了, 本篇文章就介紹到這里啦, 大家如果有疑問歡迎評(píng)論, 如果喜歡小編的文章, 記得點(diǎn)贊收藏~~

http://www.risenshineclean.com/news/45248.html

相關(guān)文章:

  • 青島開發(fā)區(qū)人才網(wǎng)青島seo優(yōu)化
  • 麗江建設(shè)信息網(wǎng)站汕頭seo排名
  • 網(wǎng)站負(fù)責(zé)人幕布照片競(jìng)價(jià)網(wǎng)絡(luò)推廣培訓(xùn)
  • 優(yōu)酷網(wǎng)站怎么做的中小企業(yè)管理培訓(xùn)班
  • 六里橋做網(wǎng)站公司長沙網(wǎng)站優(yōu)化價(jià)格
  • 現(xiàn)在用什么工具做網(wǎng)站好app拉新項(xiàng)目推廣代理
  • 編譯django做的網(wǎng)站廣州網(wǎng)站快速優(yōu)化排名
  • 香港做最好看的電影網(wǎng)站有哪些專業(yè)seo關(guān)鍵詞優(yōu)化
  • 如何新做的網(wǎng)站讓百度快速收錄嘉興seo網(wǎng)絡(luò)推廣
  • 邢臺(tái)網(wǎng)警seo電商運(yùn)營是什么意思
  • 張家港建設(shè)工程質(zhì)量監(jiān)督站網(wǎng)站策劃網(wǎng)絡(luò)營銷活動(dòng)
  • 個(gè)人網(wǎng)站建設(shè)方案書 備案品牌運(yùn)營策略有哪些
  • 一般找人做網(wǎng)站多少錢全球搜是什么公司
  • 怎么查網(wǎng)站死鏈谷歌關(guān)鍵詞優(yōu)化怎么做
  • 廊坊seo網(wǎng)站管理seo是什么專業(yè)的課程
  • 網(wǎng)站地圖什么意思優(yōu)化seo軟件
  • wordpress圖標(biāo)代碼網(wǎng)站優(yōu)化排名資源
  • 中鐵建門戶網(wǎng)登錄入口優(yōu)化公司哪家好
  • 網(wǎng)站平臺(tái)推廣百度一下瀏覽器下載安裝
  • 做網(wǎng)站做好用的軟件網(wǎng)絡(luò)營銷中的seo是指
  • java課程建設(shè)網(wǎng)站怎么做好網(wǎng)絡(luò)營銷推廣
  • 網(wǎng)站做第三方支付給企業(yè)做網(wǎng)站的公司
  • 網(wǎng)站建設(shè)前言和背景公司網(wǎng)站注冊(cè)流程和費(fèi)用
  • 大連網(wǎng)站建設(shè)方法寧波seo推廣推薦
  • 內(nèi)部網(wǎng)站搭建什么是白帽seo
  • 微信上發(fā)的鏈接網(wǎng)站怎么做的新聞?lì)^條今日新聞
  • 網(wǎng)站怎么制作成軟件青島百度網(wǎng)站排名優(yōu)化
  • 用vps做網(wǎng)站的流程三亞百度推廣公司電話
  • 怎么做淘寶網(wǎng)站賺錢技巧百度推廣技巧方法
  • 合肥市城鄉(xiāng)建設(shè)委員會(huì)網(wǎng)站無錫網(wǎng)站排名公司