前言
何為單態模式。
在一個系統中,JVM中,只能存在有一個對象的執行個體,所有程式的處理都只能調用這一個對象完成相關邏輯操作,單態模式有點在於減少了new關鍵字的調用,執行個體的初始化,節省了系統記憶體開銷。單態模式的痛點在於多線程的處理,寫法很多,真正能夠執行的,考慮的,痛點在於線程的安全問題。。。,本文進行簡單的理解闡述,如果不明白,請關注博主留下的兩篇好文 兩篇好文
http://www.blogjava.net/kenzhh/archive/2013/03/15/357824.html
http://www.cnblogs.com/dolphin0520/p/3920373.html 單態模式的正確實現
public class Truth { //volatitle 保證修飾變數在記憶體中的可見度,與java記憶體模型配合 //volatile關鍵字能禁止指令重排序,所以volatile能在一定程度上保證有序性 private volatile static Truth instance = null; private Truth(){} public static Truth getInstance(){ if(instance == null){ //保證原子性操作 synchronized (Truth.class){ if(instance == null) { instance = new Truth(); } } } return instance; } public void say(){ System.out.println("only one truth in the world!"); }}
簡單闡述
1-私人變數instance只能在內部進行初始化操作,
2-當instance為空白的時候進行一次變數賦值,從而保證返回對象不可為空白 多線程相關
1-double check [volatile|synchronized ]保證該類的安全執行緒
2-可能出現的問題為,當兩個線程同時進入getInstance方法時,線程1進行了判斷但是沒有賦值,線程2則執行下去並且賦值的同時,兩個線程沒有對公開變數進行同步,那麼線程1回來繼續執行的同時會直接new出來第二個執行個體,當然,這是在double check沒有約束的時候 synchronized關鍵字簡單闡述
保證了原子性的操作,被該關鍵字修飾以後的代碼中,在一個時間內只能有一個線程進行執行,當執行完成以後,線程將最新的值更新到記憶體中才允許存取第二個線程進入代碼塊中執行 volatile關鍵字簡單闡述
保證了線程的有序性和可見度,被該關鍵字修飾的變數,在所有的線程操作中將都是可見的,也就是說從CPU中的快取載入執行以後,引起的更改將會通知到其他CPU的快取,在這些CPU的快取中將會做失效狀態標記,從而引起其他線程執行到該變數時,從記憶體中重新載入快取. 可見度
什麼叫可見度,如圖所示,當多執行緒的時候,把變數值以及相關程式載入到快取中,由CPU進行處理,當程式對記憶體中的值進行變更處理以後,在沒有重新整理到緩衝之前,其他的線程進行讀取並操作的處理,這時候會造成讀取的值並不是最新的,進而引發安全執行緒問題,這也就是線程的可見度
有序性
有序性理解為程式執行的順序問題,在編碼的時候,我們所有的程式一般是順序執行,在載入JVM中,包括後面的實際執行中,會將我們程式執行的順序打亂,並且提高執行效率,在單線程處理中,我們並不需要考慮有序性的執行,但是多線程中,往往會因為程式的執行順序造成線程的不安全問題,比如程式之間不存在程式依賴關係,但是存在邏輯依賴關係,此時則會造成安全執行緒問題。 原子性
原子性處理,即為要麼不處理,要麼所有的程式處理完成,整個程式為一個整體,類似於資料庫的事務,但是,該程式不會發生復原,原子性是多執行緒中的必不可少的一環.