Android-Java-單例模式優化&多線程並發


上一篇博客,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;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM