1.餓漢式
這個就不用說了,直接類載入的時候例項化static ,這種方法缺點很明顯,沒用到該例項就去例項化,占用記憶體空間。
2.餓漢式
2.1 雙重檢測模式
/**
* @description:
* @author: lizijian
* @date: 2019/10/11 09:22
*/public final class singleinstance
public static singleinstance getinstance()
synchronized (singleinstance.class)
return instance;}}
}
這裡有個重要的地方是必須加volatile關鍵字,要理解為什麼要加volatile,首先要理解new singleinstance()
做了什麼。new乙個物件有幾個步驟。1.看class物件是否載入,如果沒有就先載入class物件,2.分配記憶體空間,初始化例項,3.呼叫建構函式,4.返回位址給引用。而cpu為了優化程式,可能會進行指令重排序,打亂這3,4這幾個步驟,導致例項記憶體還沒分配,就被使用了。
再用執行緒a和執行緒b舉例。執行緒a執行到new singleinstance()
,開始初始化例項物件,由於存在指令重排序,這次new操作,先把引用賦值了,還沒有執行建構函式。這時時間片結束了,切換到執行緒b執行,執行緒b呼叫new singleinstance()
方法,發現引用不等於null
,就直接返回引用位址了,然後執行緒b執行了一些操作,就可能導致執行緒b使用了還沒有被初始化的變數。
加了volatile之後,就保證new
不會被指令重排序。
至此,這就是乙個完整的懶漢模式—>執行緒安全的->雙重檢查加鎖單例模式。
2.2 內部類載入單例
class singleinstance
private static class lazysomethineholder
public static singleinstancegetinstance()
}
這種是我個人認為最好也是比較常用的方法,簡單,沒有執行緒安全問題。
2.3 列舉實現單例
列舉非常適合單例,因為列舉型別不允許繼承,執行緒安全且只能例項化一次。列舉類和餓漢式差不多,當它的class物件被載入就會例項化列舉型別的例項變數,可以改造為懶載入。如下
public final class singleinstance
public static singleinstance getinstance()
private enum enumsingleinstanceholder
public singleinstance getinstance()
}}
單例模式幾種寫法
1.餓漢式 public class singleton public static singleton getinstance 2.懶漢式 public class singleton 雙層檢測鎖 public static singleton getinstance return instanc...
單例模式的幾種寫法
所謂單例模式就是確保某乙個類只有乙個例項,並且提供乙個全域性訪問點。例如 執行緒池 快取 對話方塊等等 1 餓漢模式 保證執行緒安全 public class singleton public static singleton getinstance 2 懶漢模式 不保證執行緒安全 public c...
單例模式的幾種寫法
1.懶漢式 public class singleinstance1 private static singleinstance1 instance public static singleinstance1 getinstance return instance 該程式缺點是執行緒不安全 publ...