美文网首页
kotlin 单例模式的多种实现

kotlin 单例模式的多种实现

作者: 100个大西瓜 | 来源:发表于2022-09-21 00:32 被阅读0次

    线程不安全的实现方式

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    /**
     * 线程不安全的单例:传统方法
     */
    class ThreadNotSafeSingleton private constructor() {
    
        init {
            println("ThreadNotSafeSingleton")
        }
    
        companion object {
    
            private var singleton: ThreadNotSafeSingleton? = null
                get() {
                    if (field == null) {
                        field = ThreadNotSafeSingleton()
                    }
                    return field
                }
    
            @JvmStatic
            fun getInstance(): ThreadNotSafeSingleton {
                return singleton!!
            }
        }
    
    }
    
    fun main() {
        thread {
            println("thread ${ThreadNotSafeSingleton.getInstance()}")
        }
        println("main ${ThreadNotSafeSingleton.getInstance()}")
    
    }
    

    《head first 设计模式》中对于单例有三种线程安全的实现方式

    1.直接同步getInstance()方法,

    肯定线程安全,但会有性能问题;

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    /**
     * 线程安全的单例
     * 使用锁
     */
    class ThreadSafeSingleton private constructor() {
    
        init {
            println("ThreadSafeSingleton")
        }
    
        companion object {
            private var singleton: ThreadSafeSingleton? = null
    
            @JvmStatic
            @Synchronized
            fun getInstance(): ThreadSafeSingleton {
                if (singleton == null) {
                    singleton = ThreadSafeSingleton()
                }
                return singleton!!
            }
    
        }
    }
    
    fun main() {
        thread {
            println("thread ${ThreadSafeSingleton.getInstance()}")
        }
        println("main ${ThreadSafeSingleton.getInstance()}")
    }
    

    2.在getInstance()中双重检查加锁,

    只有单例未创建之前才会进入锁的代码块,减少不必要的同步次数,提高性能;

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    /**
     * 线程安全的单例
     * 使用双重检查加锁的方法:只适用于jdk5之后的
     */
    class DoubleCheckSingleton private constructor() {
    
        init {
            println("DoubleCheckSingleton")
        }
    
        companion object {
            @Volatile
            private var sSingleton: DoubleCheckSingleton? = null
    //            get() {
    //                if (field == null) {
    //                    synchronized(DoubleCheckSingleton::class) {
    //                        if (field == null) {
    //                            field = DoubleCheckSingleton()
    //                        }
    //                    }
    //                }
    //                return field
    //            }
    
            @JvmStatic
            fun getInstance(): DoubleCheckSingleton {
                if (sSingleton == null) {
                    synchronized(DoubleCheckSingleton::class) {
                        if (sSingleton == null) {
                            sSingleton = DoubleCheckSingleton()
                        }
                    }
                }
                return sSingleton!!
            }
        }
    }
    
    
    fun main() {
        thread {
            println("thread ${DoubleCheckSingleton.getInstance()}")
        }
        println("main ${DoubleCheckSingleton.getInstance()}")
    
    }
    

    3.使用饿汉模式(急切实例化),

    直接创建出该对象,但这样在没有使用到该对象之前,提前创建会多多少少浪费资源;

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    /**
     * 饿汉模式的单例:线程安全
     */
    class HungrySingleton private constructor() {
        init {
            println("HungrySingleton")
        }
    
        companion object {
            private var singleton = HungrySingleton()
    
            @JvmStatic
            fun getInstance(): HungrySingleton {
                return singleton
            }
        }
    
    }
    
    
    fun main() {
        // TODO: 理论上 要先打印 "HungrySingleton"再打印 "main--"的
        //  可能是kotlin 编译出来的多了个HungrySingletonKt.class,而这main函数在这个类里面
        println("main--")
        thread {
            println("thread ${HungrySingleton.getInstance()}")
        }
        println("main ${HungrySingleton.getInstance()}")
    
    }
    

    此外还有java的静态内部类实现的单例,kotlin版本

    参考来源

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    /**
     *相当于JAVA的静态内部类单例
     * 参考自
     * https://blog.csdn.net/qq_40987010/article/details/122499694
     */
    class InnerSingleton private constructor() {
        init {
            println("InnerSingleton")
        }
    
        private object InnerHolder {
            val singleton = InnerSingleton()
        }
    
        companion object {
            @JvmStatic
            fun getInstance(): InnerSingleton {
                return InnerHolder.singleton
            }
        }
    
    }
    
    fun main() {
        thread {
            println("thread ${InnerSingleton.getInstance()}")
        }
        println("main ${InnerSingleton.getInstance()}")
    }
    

    最后当然少不了kotlin自带的object关键字 的单例模式

    如果构造方法没有参数,使用这种方式是最简单的

    package com.sheby.hfdpkt.chap05.singleton
    
    import kotlin.concurrent.thread
    
    object KotlinSingleton {
        init {
            println("create KotlinSingleton ${Thread.currentThread().name}}")
            Thread.sleep(200)
        }
    }
    
    fun main() {
        thread {
            println("thread $KotlinSingleton")
        }
        println("main $KotlinSingleton")
    }
    

    github源码

    相关文章

      网友评论

          本文标题:kotlin 单例模式的多种实现

          本文链接:https://www.haomeiwen.com/subject/pztyortx.html