考虑性能和线程安全的java单例模式实现
2014-09-08 22:35
309 查看
yao__shun__yu转载的一篇博客详细的介绍了实现单例模式的几种方法:/article/2435148.html,对性能和线程安全的阐述写得特别好。lz自己也把单例模式写了写,但不免还是会有些疏忽,本文主要是写写自己的心得和以及自己觉得还需注意的地方,对原文的第5小节也提出了一点改进,算是这篇文章的一点补充吧。
单例模式的含义为一个Singleton类只有它自身的一个实例。本文1-4小节就性能和线程安全方面易出现的问题进行了探讨,对此有兴趣的读者可以参考其中的内容。第5小节提出了较好的解决方案,想了解的读者也可以直接看这里,第5小节不以1-4小节为基础。
首先,对yao__shun__yu转载的博客中的要点概括如下:
1.饥饿模式:使用了静态工厂方法,对象设为static,在声明时便初始化了,在getSingleInstance方法中直接返回该对象,可能带来潜在的性能问题。
2.懒汉模式:使用了延迟加载方法,对象设为static,在声明时设为null,在使用时,在getSingleInstance方法中,如果对象为null则初始化,解决了性能问题,但是是线程不安全的。
3.在懒汉模式的getSingleInstance方法前加Synchronized,解决了线程安全问题,但是并发度较低。
4.Double-Checked Lock:只对创建对象的语句进行同步,可以得到很好的并发度,但是可能会得到未完整初始化的对象。因为初始化需要一定时间,如当线程A未完全初始化对象时,此时对象已经不是null了,线程B在第9行判断对象不为null后就可能返回一个未完全初始化的对象。
5.Initialization-on-demand
holder:使用一个静态类SingletonHolder来初始化Singleton对象(注意是Singleton对象而不是SingletonHolder对象噢,原因请参看本文最开始的单例模式定义),SingletonHolder只在被使用时才被初始化,保证了性能和线程安全。并且由于java的构造方法默认是public的,需要将Singleton的构造方法写成private,避免其他类直接调用Singleton的构造方法获取实例。
Double-Checked Lock:http://en.wikipedia.org/wiki/Double-checked_locking
Initialzation on Demand Holder: http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
单例模式的含义为一个Singleton类只有它自身的一个实例。本文1-4小节就性能和线程安全方面易出现的问题进行了探讨,对此有兴趣的读者可以参考其中的内容。第5小节提出了较好的解决方案,想了解的读者也可以直接看这里,第5小节不以1-4小节为基础。
首先,对yao__shun__yu转载的博客中的要点概括如下:
1.饥饿模式:使用了静态工厂方法,对象设为static,在声明时便初始化了,在getSingleInstance方法中直接返回该对象,可能带来潜在的性能问题。
public final class EagerSingleton { private static EagerSingleton singObj = new EagerSingleton(); private EagerSingleton(){ } public static EagerSingleton getSingleInstance(){ return singObj; } }
2.懒汉模式:使用了延迟加载方法,对象设为static,在声明时设为null,在使用时,在getSingleInstance方法中,如果对象为null则初始化,解决了性能问题,但是是线程不安全的。
public final class LazySingleton { private static LazySingleton singObj = null; private LazySingleton(){ } public static LazySingleton getSingleInstance(){ if(null == singObj ) singObj = new LazySingleton(); return singObj; } }
3.在懒汉模式的getSingleInstance方法前加Synchronized,解决了线程安全问题,但是并发度较低。
public final class ThreadSafeSingleton { private static ThreadSafeSingleton singObj = null; private ThreadSafeSingleton(){ } public static Synchronized ThreadSafeSingleton getSingleInstance(){ if(null == singObj ) singObj = new ThreadSafeSingleton(); return singObj; } }
4.Double-Checked Lock:只对创建对象的语句进行同步,可以得到很好的并发度,但是可能会得到未完整初始化的对象。因为初始化需要一定时间,如当线程A未完全初始化对象时,此时对象已经不是null了,线程B在第9行判断对象不为null后就可能返回一个未完全初始化的对象。
public final class DoubleCheckedSingleton { private static DoubleCheckedSingletonsingObj = null; private DoubleCheckedSingleton(){ } public static DoubleCheckedSingleton getSingleInstance(){ if(null == singObj ) { Synchronized(DoubleCheckedSingleton.class){ if(null == singObj) singObj = new DoubleCheckedSingleton(); } } return singObj; } }
5.Initialization-on-demand
holder:使用一个静态类SingletonHolder来初始化Singleton对象(注意是Singleton对象而不是SingletonHolder对象噢,原因请参看本文最开始的单例模式定义),SingletonHolder只在被使用时才被初始化,保证了性能和线程安全。并且由于java的构造方法默认是public的,需要将Singleton的构造方法写成private,避免其他类直接调用Singleton的构造方法获取实例。
public class Singleton { private Singleton(){ } private static class SingletonHolder { public final static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
Double-Checked Lock:http://en.wikipedia.org/wiki/Double-checked_locking
Initialzation on Demand Holder: http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
相关文章推荐
- Oracle 10g数据库中,当在数据库中创建用户时,基于应用性能和管理方面的考虑,最好为不同的用户创建独立的表空间。 那么创建表空间的步骤是怎样实现的呢?本文我们主要就介绍了这一部分内容,接下来就让
- 智能指针的一个实现(没有考虑线程安全)
- 对改善Dictionary时间性能的思考及一个线程安全的Dictionary实现
- 用js实现下列功能,将给定的数字转化为千分位的格式,如把"10000"转化为"10,000",并考虑性能方面的因素
- 如何利用内部类的类型封装功能实现线程安全的类以提高程序的性能
- 关于单例模式这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。
- java单例模式详解完美实现(包括反射破坏的防止和线程安全)
- 百度面试题:自己实现strlen,考虑32位,64位机器,考虑性能
- Java性能优化(11):考虑实现Comparable接口
- 动手实现TCP的Nagle算法,提高网络应用程序的性能
- Hibernate程序性能优化的考虑要点
- 也谈用反射实现Enum→String映射:一种重视性能的方法
- asp.net 2.0页面性能的考虑--异步页面处理模型
- Hibernate程序性能优化的考虑要点
- windows mobile程序性能考虑
- Hibernate程序性能优化的考虑要点
- 从 ASPX 页面进行 Web 服务调用时的性能考虑
- java实现线程安全的三大利器
- asp.net 2.0页面性能的考虑--异步页面处理模型
- 判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)