使用单例模式优化代码
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()方法也不需要使用同步关键字。
但是,这种方式真的可以确保在系统中只存在唯一的实例了吗??有没有例外情况呢.................................[夜深了,先睡觉]
以上是关于使用单例模式优化代码的主要内容,如果未能解决你的问题,请参考以下文章