設計模式中最簡單的模式就要數單例模式了。
那么什么是單例模式呢? 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。

上圖為單例模式的結構示意圖。
那么為什么要使用單例模式呢?
簡單來說:單例模式的存在,一則,解決多線程并發訪問的問題。二則,節約系統內存,提交系統運行的效率,提高系統性能。
下面我們就來看看程序中是怎么實現單例模式的:
一般我們設計一個類都是這樣的:
public class Abc{ PRivate Abc() { }; }然后在其他部分調用:
public class Cbd{ public Cbd() { Abc n1,n2; n1=new Abc(); n2=new Abc(); }}但這樣Abc這個類就會出現好多實體并不好控制,下面我們來改變一下啊Abc這個類的結構從而實現單例模式:public class Abc{ private static Abc uniqeInstance_Abc = null; //通過內置私有靜態參數實現單例狀態 private Abc(){ }; //外部只能調用單例,單例實體有類內部控制 public static Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}這樣我們變實現了單例模式public class Cbd{ public Cbd() { Abc n1,n2; n1=Abc.getInstance_Abc(); }}可以看到Abc這個類的構造函數變成了private修飾,所以并不能在其他類中new出來只能通過調用getxxx函數來使用,這就保證了單例性。
寫一個小例子,模擬一下我們計算機中的CPU處理程序:

package com.java.jikexueyuan.singleton;public class Cpu { private boolean idle; private boolean compute; public volatile static Cpu uniqueInstance_cpu = null; int num; private Cpu() { idle = true; compute = false; num = 101; } public static Cpu getInstance() { if (uniqueInstance_cpu == null) { synchronized (Cpu.class) { if (uniqueInstance_cpu == null) { uniqueInstance_cpu = new Cpu(); } } } return uniqueInstance_cpu; } //判斷cpu是否為空閑狀態 public boolean isIdle() { if (idle) { idle = false; compute = false; System.out.println("cpu空閑"); return true; } else { System.out.println("cpu繁忙"); return true; } } //cpu計算結束 public void compute_over() { if ((!idle) && compute) { idle = true; compute = false; System.out.println("cpu計算完成"); } } //啟動cpu計算過程 public void computing() { if ((!idle) && (!compute)) { compute = true; System.out.println("cpu正在計算,計算cpu編號為" + num); } }}我們來調用一下:public class test { public static void main(String[] args) { for(int i = 0; i < 5 ; i++) { Cpu c1 = Cpu.getInstance(); if(c1.isIdle()) { c1.computing(); c1.compute_over(); } } }}
其實這樣設計的單例模式有一個重大隱患,就是當兩個線程同時創建一個Abc類的時候,可以會new出來兩個實體而導致嚴重的錯誤。。。
解決傳統的解決方式呢,有三種:
第一種:添加同步鎖:
public class Abc{ private static Abc uniqeInstance_Abc = null; //通過內置私有靜態參數實現單例狀態 private Abc(){ }; //外部只能調用單例,單例實體有類內部控制 //添加了同步所,保證不會有兩個線程同是進入該方法 public static synchronized Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}第二種:急切創建法:public class Abc{ //通過內置私有靜態參數實現單例狀態 //直接創建實例 private static Abc uniqeInstance_Abc = new Abc(); private Abc(){ }; //外部只能調用單例,單例實體有類內部控制 public static Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}第三種:雙重檢查加鎖法public class Abc{ //通過內置私有靜態參數實現單例狀態 //volatile關鍵字確保多線程在處理時的正確性 private volatile static Abc uniqeInstance_Abc = new Abc(); private Abc(){ }; //外部只能調用單例,單例實體有類內部控制 public static Abc getInstance_Abc() { //多重加鎖 if (uniqeInstance_Abc == null) { synchronized (Abc.class) { if (uniqeInstance_Abc == null) { uniqeInstance_Abc = new Abc(); } } } return uniqeInstance_Abc; }}單例模式的使用場景:
1.資源共享的情況下,避免由于資源操作時導致的性能或損耗等。如上述中的日志文件,應用配置。 2.控制資源的情況下,方便資源之間的互相通信。如線程池等。
新聞熱點
疑難解答