Kotlin比较多种单例的写法,哪一种单例性能最优?

2025-03-11 08:52 Kotlin比较多种单例的写法,哪一种单例性能最优?已关闭评论

在Kotlin中有多种实现单例的方式,常见的有以下几种,它们在性能和特点上各有不同:

饿汉式单例

class EagerSingleton {
    companion object {
        val instance: EagerSingleton = EagerSingleton()
    }
}

这种方式在类加载时就创建了单例实例。优点是实现简单,并且在多线程环境下天然线程安全,因为类加载由JVM保证线程安全。缺点是如果单例对象创建开销很大,而应用程序可能永远不会用到这个单例,那么就会造成资源浪费。从性能角度,只要类加载完成,获取实例的操作是非常快的,没有任何额外的同步开销。

懒汉式单例(线程不安全)

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

这种方式在第一次调用 getInstance 方法时才创建实例,实现了延迟加载。但是在多线程环境下,如果多个线程同时调用 getInstance 方法,并且 instancenull,就可能会创建多个实例,线程不安全。性能方面,在单线程环境下,首次创建实例会有一定开销,但后续获取实例很快;然而在多线程环境下,由于可能创建多个实例,可能导致资源浪费以及逻辑错误。

懒汉式单例(线程安全,同步方法)

class SynchronizedLazySingleton {
    companion object {
        private var instance: SynchronizedLazySingleton? = null
        @Synchronized
        fun getInstance(): SynchronizedLazySingleton {
            if (instance == null) {
                instance = SynchronizedLazySingleton()
            }
            return instance!!
        }
    }
}

通过在 getInstance 方法上添加 @Synchronized 注解,保证了多线程环境下的线程安全,每次只有一个线程能够进入该方法创建实例。但是这种方式的性能开销较大,因为每次调用 getInstance 方法都需要进行同步操作,即使实例已经创建好了,也会有同步开销。

懒汉式单例(线程安全,双重检查锁定)

class DoubleCheckedSingleton {
    companion object {
        private var instance: DoubleCheckedSingleton? = null
        fun getInstance(): DoubleCheckedSingleton {
            if (instance == null) {
                synchronized(this) {
                    if (instance == null) {
                        instance = DoubleCheckedSingleton()
                    }
                }
            }
            return instance!!
        }
    }
}

这种方式结合了延迟加载和线程安全。首先进行一次非同步的判空检查,如果 instance 不为 null,则直接返回实例,避免了不必要的同步开销。只有当 instancenull 时,才进入同步块进行第二次判空检查并创建实例。性能上,在实例创建之后,获取实例的操作没有同步开销,相对高效。

枚举单例

enum class EnumSingleton {
    INSTANCE;
}

枚举单例是一种简洁且高效的单例实现方式。枚举类型在JVM中是线程安全的,并且只会被加载一次。它还可以防止反射和反序列化破坏单例。性能上,和饿汉式单例类似,在类加载时就创建好实例,获取实例的操作非常快。

性能最优分析

从性能最优角度来说,如果应用程序一开始就需要单例实例,或者单例实例创建开销不大,饿汉式单例和枚举单例是不错的选择,它们在类加载时创建实例,后续获取实例没有额外开销。

如果需要严格的延迟加载,并且多线程环境下要求高效获取实例,双重检查锁定的懒汉式单例比较合适,在实例创建后获取实例没有同步开销。

如果单例创建开销大且应用程序可能永远不会用到单例,同时对线程安全要求不高(单线程环境),线程不安全的懒汉式单例可以实现延迟加载且性能较好。而同步方法的懒汉式单例由于每次获取实例都有同步开销,性能相对较差,一般不推荐使用。

总体而言,没有绝对性能最优的单例写法,需要根据具体的应用场景和需求来选择合适的单例实现方式。

当前文章价值4.7元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章

来源:每日教程每日一例,深入学习实用技术教程,关注公众号TeachCourse
转载请注明出处: https://teachcourse.cn/3810.html ,谢谢支持!

资源分享

分类:kotlin 标签:,
Android学习笔记一:Java类加载过程 Android学习笔记一:Java类加载
Oracle VM VirtualBox启动提示“创建COM对象失败” Oracle VM VirtualBox启动提
014-wordpress如何实现配置CORS策略来限制哪些域可以访问你的API 014-wordpress如何实现配置COR
Android面试笔记一:三二一家具 Android面试笔记一:三二一家具

评论已关闭!