单例模式()
当使用SingletoncreateString()执行任务时程序输出
Singleton is create
createString in Singleton
可以看到虽然此时并没有使用单例类但它还是被创建出来这也许是开发人员所不愿意见到的为了解决这个问题并以此提高系统在相关函数调用时的反应速度就需要引入延迟加载机制
public class LazySingleton {
private LazySingleton(){
Systemoutprintln(LazySingleton is create)
//创建单例的过程可能会比较慢
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance() {
if (instance==null)
instance=new LazySingleton()
return instance;
}
}
首先对于静态成员变量instance初始值赋予null确保系统启动时没有额外的负载其次在getInstance()工厂方法中判断当前单例是否已经存在若存在则返回不存在则再建立单例这里尤其还要注意getInstance()方法必须是同步的否则在多线程环境下当线程正新建单例时完成赋值操作前线程可能判断instance为null故线程也将启动新建单例的程序而导致多个实例被创建故同步关键字是必须的
使用上例中的单例实现虽然实现了延迟加载的功能但和第一种方法相比它引入了同步关键字因此在多线程环境中它的时耗要远远大于第一种单例模式以下测试代码就说明了这个问题
@Override
public void run(){
for(int i=;i<;i++)
SingletongetInstance()
//LazySingletongetInstance()
Systemoutprintln(spend:+(SystemcurrentTimeMillis()begintime))
}
开启个线程同时完成以上代码的运行使用第种类型的单例耗时ms而使用LazySingleton却相对耗时约ms性能至少相差个数量级
注意在本书中会使用很多类似的代码片段用于测试不同代码的执行速度在不同的计算机上其测试结果很可能与笔者不同读者大可不必关心测试数据的绝对值只要观察用于比较的目标代码间的相对耗时即可
为了使用延迟加载引入的同步关键字反而降低了系统性能是不是有点得不偿失呢?为了解决这个为问题还需要对其进行改进
public class StaticSingleton {
private StaticSingleton(){
Systemoutprintln(StaticSingleton is create)
}
private static class SingletonHolder {
private static StaticSingleton instance = new StaticSingleton()
}
public static StaticSingleton getInstance() {
return SingletonHolderinstance;
}
}
在这个实现中单例模式使用内部类来维护单例的实例当StaticSingleton被加载时其内部类并不会被初始化故可以确保当StaticSingleton类被载入JVM时不会初始化单例类而当getInstance()方法被调用时才会加载SingletonHolder从而初始化instance同时由于实例的建立是在类加载时完成故天生对多线程友好getInstance()方法也不需要使用同步关键字因此这种实现方式同时兼备以上两种实现的优点
注意使用内部类的方式实现单例既可以做到延迟加载也不必使用同步关键字是一种比较完善的实现
返回目录Java程序性能优化让你的Java程序更快更稳定
编辑推荐
Java程序设计培训视频教程
JEE高级框架实战培训视频教程
JME移动开发实战教学视频
Visual C++音频/视频技术开发与实战
Oracle索引技术
ORACLEG数据库开发优化指南