上一篇博客,Android-Java單例模式,介紹了在真實開發過程中,普遍使用的幾種單例模式,而今天這篇博客,將要對單利模式進行優化 並且 通過多線程並發來分析
單利模式的優化:
對於為什么會出現安全問題,可以看Android-多線程安全問題-synchronized,博客
package android.java.thread14; /** * 單例模式優化 */ public class SingletonPattern { private SingletonPattern() { } /** * 俄漢式:多線程並發是安全🔐的,因為此類一加載就實例化了 */ private static final SingletonPattern SINGLETON_PATTERN = new SingletonPattern(); public static SingletonPattern getInstance1() { return SINGLETON_PATTERN; // 如果這里對SINGLETON_PATTERN共享數據進行操作,多線程並發不安全! } /** * 懶漢式:需要進行 靜態方法 synchronized(鎖🔒 SingletonPattern.class) * 此方式性能低:因為線程每次調用此方法都需要判斷鎖 * 需要明白CPU執行執行多線程的隨機性,並用以下代碼方式解決 多線程並發 */ private static SingletonPattern singletonPattern = null; public static synchronized SingletonPattern getInstance2() { if (null == singletonPattern) { // 這里對singletonPattern共享數據進行操作,多線程並發不安全! singletonPattern = new SingletonPattern(); // 這里對singletonPattern共享數據進行操作,多線程並發不安全! System.out.println(Thread.currentThread().getName() + ">>>>>>> 懶漢式1 單例模式實例化了"); } return singletonPattern; } /** * 懶漢式:對性能要求高 可以 synchronized + if雙重判斷 * 需要明白CPU執行執行多線程的隨機性,並用以下代碼方式解決 多線程並發 */ private static SingletonPattern singleton = null; private static final Object objectLock = new Object(); // 定義一把同步鎖🔒 public static SingletonPattern getInstance3() { if (null == singleton) { synchronized (objectLock) { if (null == singleton) { singleton = new SingletonPattern(); System.out.println(Thread.currentThread().getName() + ">>>>>>> 懶漢式2 單例模式實例化了"); } } } return singleton; } }
多線程並發實例化單例模式:
package android.java.thread14; /** * 執行任務,此任務可以給線程運行 */ class DoRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { // doRunnable1(); // doRunnable2(); doRunnable3(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } private void doRunnable1() { SingletonPattern.getInstance1(); } private void doRunnable2() { SingletonPattern.getInstance2(); } private void doRunnable3() { SingletonPattern.getInstance3(); } } public class Test { public static void main(String[] args) { // 實例化任務 DoRunnable doRunnable = new DoRunnable(); // 開啟三個線程 new Thread(doRunnable).start(); new Thread(doRunnable).start(); new Thread(doRunnable).start(); } }
執行結果,CPU隨機性:

俄漢式:性能提高的同時 又保證了多線程的並發-安全
/** * 懶漢式:對性能要求高 可以 synchronized + if雙重判斷 * 需要明白CPU執行執行多線程的隨機性,並用以下代碼方式解決 多線程並發 */ private static SingletonPattern singleton = null; private static final Object objectLock = new Object(); // 定義一把同步鎖🔒 public static SingletonPattern getInstance3() { // 假設CPU隨機第四步:Thread-1 現在判斷不為null,進不去 if (null == singleton) { // 假設CPU隨機第一步:Thread-0 執行到這里CPU去執行其他Thread-2線程了 假設CPU隨機第二步:Thread-2線程在這里判斷鎖,然后進去了 synchronized (objectLock) { if (null == singleton) { singleton = new SingletonPattern(); System.out.println(Thread.currentThread().getName() + ">>>>>>> 懶漢式2 單例模式實例化了"); } } // 假設CPU隨機第三步:Thread-2 執行完畢 } return singleton; }
