Kotlin單例方法

這篇文章簡單介紹下kotlin中單例的實現方法。

1:餓漢式

java的實現很簡單,我們直接上代碼:

public class SingleTon1 {
    private static SingleTon1 singleTon1 = new SingleTon1();

    private SingleTon1() {
    }

    public static SingleTon1 getInstance() {
        return singleTon1;
    }
}

那kotlin怎麼寫呢?
這裏就更簡單了,只用到object關鍵字就行:

object SingleTon1 {
}

這就是kotlin中的餓漢式單例。
這裏我們簡單看下字節碼文件:
怎麼看呢?
首先我們找到studio的tools->kotlin然後點擊show kotlin bytecode:
在這裏插入圖片描述
在這裏插入圖片描述
右側會出現 kotlin bytecode,點擊就可以了。
在這裏插入圖片描述
接着我們點擊decompile,
在這裏插入圖片描述

2:懶漢式

我們還是先看下java的寫法:

/**
 * create by zj on 2020/7/1
 * 懶漢式
 */
public class SingleTon2 {
    private static SingleTon2 singleTon;

    private SingleTon2() {
    }

    public static SingleTon2 getInstance() {
        if (singleTon == null) {
            singleTon = new SingleTon2();
        }
        return singleTon;
    }
}

kotlin這裏就有兩種寫法了,我們完全可以照着java的模式來寫一個:

class SingleTon2 {
    companion object {
        private var instance2: SingleTon2? = null
        fun getInstance(): SingleTon2 {
            if (instance2 == null) {
                instance2 = SingleTon2()
            }
            return instance2!!
        }
    }
}

另一種就是完全是kotlin獨有了,這裏我們用到的lazy。

class SingleTon2 {
    companion object {
        //LazyThreadSafetyMode.NONE 沒有鎖
       val instance by lazy(LazyThreadSafetyMode.NONE) {
           SingleTon2()
      }
    }
}

3:同步鎖

public class SingleTon3 {
    private static SingleTon3 instance;

    private SingleTon3() {
    }

    public static synchronized SingleTon3 getInstance() {
        if (instance == null) {
            instance = new SingleTon3();
        }
        return instance;
    }
}

我們知道這樣就實現了線程安全的懶加載,kotlin中跟java類似,只是synchronized來替換。

class SingleTon3 {
    companion object {
        private var instance: SingleTon3? = null

        @Synchronized
        fun getInstance(): SingleTon3 {
            if (instance == null) {
                instance = SingleTon3()
            }
            return instance!!
        }
    }
}

4:Double Check(優化的線程安全單例)
再上一步中getInstance方法我們直接加了synchronize同步,在這裏我們則將synchronize加載方法裏面,只有在實例爲空的時候,才同步。

public class SingleTon4 {
    private static volatile SingleTon4 instance;

    private SingleTon4() {
    }

    public static SingleTon4 getInstance() {
        if (instance == null) {
            synchronized (SingleTon4.class) {
                if (instance == null) {
                    instance = new SingleTon4();
                }
            }
        }
        return instance;
    }
}

kotlin這裏也有兩種寫法:

class SingleTon4 {
    companion object {
        @Volatile
        private var instance: SingleTon4? = null

        fun getInstance(): SingleTon4 {
            if (instance == null) {
                synchronized(this) {
                    if (instance == null) {
                        instance = SingleTon4()
                    }
                }
            }
            return instance!!
        }
 
    }
}

這裏volatile也是使用註解的方法來表示、
那麼kotlin中的正規寫法是什麼呢?
在第二種方法裏面我們有見到LazyThreadSafetyMode.NONE,這裏我們還是用的LazyThreadSafetyMode,只是值使用的是LazyThreadSafetyMode.SYNCHRONIZED。

class SingleTon4 {
    companion object {
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            SingleTon4()
        }
    }
}

LazyThreadSafetyMode 是個枚舉類,如下:

public enum class LazyThreadSafetyMode {

    /**
     * Locks are used to ensure that only a single thread can initialize the [Lazy] instance.
     */
    SYNCHRONIZED,

    /**
     * Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value,
     * but only the first returned value will be used as the value of [Lazy] instance.
     */
    PUBLICATION,

    /**
     * No locks are used to synchronize an access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined.
     *
     * This mode should not be used unless the [Lazy] instance is guaranteed never to be initialized from more than one thread.
     */
    NONE,
}

5:靜態內部類

kotlin中類似的寫法如下:

class SingleTon5 {
    companion object {
        fun getInstance() = Holder.instance
    }

    private object Holder {
        val instance = SingleTon5()
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章