使用单例模式优化代码

Posted 小胡的技术之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用单例模式优化代码相关的知识,希望对你有一定的参考价值。

前言

单例模式,是一种对象的创建模式,用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例,在JAVA语言中,这样的行为可以带来2大好处

1.对于频繁使用的对象,可以省略创建对象所花费的时间。

2.由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间

单例模式代码

核心在于通过一个接口返回唯一的对象实例:

注意:单例类必须要有一个private访问级别的构造函数,只有这样,才能确保单例不会再系统中的其他代码内被实例化,其次,instatnce成员变量和getInstance()方法必须是static的

上面代码模式的弊端

上面的实现方式非常简单,而且十分可靠,唯一的不足就是无法对instance实例做延迟加载。假如单例的创建过程很慢,而由于Instance成员变量是static定义的,因此,在JVM加载单例类的时候,单例对象就会被创建,这个单例类在系统中还扮演其他角色,那么在任何使用这个单例类的地方都会初始化这个单例变量,而不管是否被用到。比如单例类作为String工厂,用于创建一些字符串。

(该类既用于创建单例Singleton,又用于创建String对象)

使用单例模式优化代码

结果:

使用单例模式优化代码

可以看到,虽然当时没有 使用单例类,但是它还是被创建出来了。如何解决这个问题,引入延迟加载机制。

使用单例模式优化代码

1.首先,对于静态成员变量instance初始值赋予null,确保系统启动时,没有额外的负载,

2.其次,在getInstance()工厂方法中,判断当前单例是否已经存在,如果存在则返回,如果不存在则再次创建单例,

3.这里尤其注意getInstance()方法必须是同步的,否则多线程的情况下,当线程1正新建单例的时候,完成赋值操作之前,线程2可能判断instance为null,故线程2也将启动新建单例的程序,而导致多个实例被创建。关键字很重要

出现了新的问题

使用上例中的单例实现,虽然实现了延迟加载功能,但是和第一种方法相比,它引入了同步关键字,在多线程的环境下,它的时耗远远大于第一种单例模式

看下面的测试代码

 开启5个线程同时完成以上代码的运行。使用第1种类型的单例耗时0ms,而使用LazySingleton却相对耗时约390ms。性能至少相差2个数量级

继续改进

1.单例模式使用内部类来维护单例的实例,当StaticSingleton被加载时,其内部类并不会被初始化,故可以确保当StaticSingleton类被加载入JVM时,不会初始化单例类,

2.而当getInstance方法被调用时候,才会加载SingletonHolder,从而初始化instance,同时,由于实例的建立是在类的加载时完成的,故天生对多线程友好,getInstance()方法也不需要使用同步关键字。

但是,这种方式真的可以确保在系统中只存在唯一的实例了吗??有没有例外情况呢.................................[夜深了,先睡觉]

以上是关于使用单例模式优化代码的主要内容,如果未能解决你的问题,请参考以下文章

Python中的单例模式的几种实现方式的及优化

Java程序性能优化-单例模式(1)

Android-Java-单例模式优化&多线程并发

单例模式,饿汉与懒汉

Python中的单例模式的几种实现方式的及优化

Python中的单例模式的几种实现方式的优缺点及优化