@BertLee
2017-08-03T06:06:00.000000Z
字数 2636
阅读 1197
单例模式随处可见,用处也很大,但是写好一个单例模式很不容易,拔出萝卜带出泥,面试也经常会被问到,今天就来总结一下。
什么是单例?
- 单例类只能有1个实例对象,
- 单例类必须自己创建该实例,别人不能创建
- 单例类必须该所有其他对象提供该实例
/*** 1-饿汉式单例类*/public class EagerSingleton {//private保证实例不被直接访问,static保证只有1份,final保证这1份不被修改private static final EagerSingleton instance = new EagerSingleton();//private保证不被其它类new出来private EagerSingleton(){}//静态工厂方法,给其它对象提供相同方法public static EagerSingleton getInstance(){return instance;}}
优点:在类被加载的时候,就创建了实例,多线程下是安全的。
缺点:创建单例的时机过于急躁,在没有用到单例之前,占用了内存,而且初始化加载的配置到最后可能并不是我们想要的
/*** 2-懒汉式单例模式*/public class LazySingleton {//当getInstance方法被调用时才会被创建,没有final修饰,不能保证线程安全private static LazySingleton instance = null;private LazySingleton(){}public synchronized static LazySingleton getInstance() {if(instance == null){//在多线程情况下,实例的创建会出现现不一致情况,因此要加synchronizedinstance = new LazySingleton();}return instance;}}
优点:保证了线程安全,只有在被用到的情况下,才会初始化实例,节省了空间
缺点:synchronized加在了方法上,同步过度,每个线程执行getInstance方法时都要同步,执行效率比较低,最好的情况是只在实例第一次初始化时,执行同步
/*** 3-双重检查锁单例模式*/public class Singleton implements Serializable {private static volatile Singleton instance = null;private Singleton() {}public static Singleton getInstance() {//如果实例已经被创建,则不被同步,这样可以提高执行效率if (instance == null) {//实例初次被创建时,可能有多个线程,所以要加锁,同步synchronized (Singleton.class) {//实例只可以被创建1次,等其它阻塞线程执行时,不在初始化if (instance == null) {//该赋值操作,只在当前线程的工作区中执行,什么时候会写到主存,由jvm执行,因此要加volatile,让其它线程可知instance = new Singleton();}}}return instance;}//防被反序列化时创建多个实例对象private Object readResolve() {return getInstance();}//防止通过反射创建多个实例,重写getClass方法private static Class getClass(String classname)throws ClassNotFoundException {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();if (classLoader == null)classLoader = Singleton.class.getClassLoader();return (classLoader.loadClass(classname));}}
优点:理想很丰满,思路清晰,只在初始化实例时,同步
缺点:现实很残酷,在java旧版本时,支持的并不很好,原因在于instance = new Singleton()在多线程情况下,可能出现构造方法还没执行,就被其它线程拿走了。现如今violate已被优化,可以实现,但是效率并不高
/*** 4-内部类单例模式*/public class InnerClassSingleton {private static class SingletonHolder{public static final InnerClassSingleton instance = new InnerClassSingleton();}public static InnerClassSingleton getInstance(){return SingletonHolder.instance;}}
优点:由jvm保证线程安全,只有被用到时,才会被初始化
缺点:序列化和反序列化支持比较差
/*** 5-枚举单例类*/public enum SingletonEnum {INSTANCE; //单例实例private DataSource dataSource;private SingletonEnum(){//初始化单例的内容,添加dataSource的配置内容}public Connection getConnection() throws SQLException {return dataSource.getConnection();}}
优点:最佳实践,完美解决各种问题
缺点:项目中运用的少
老朽在撰笔之时,参考了以下几篇博文,如有不妥之处,请与老朽联系。
http://blog.csdn.net/huangyuan_xuan/article/details/52193006
http://blog.csdn.net/yangkai_hudong/article/details/50628172
http://www.cnblogs.com/java-my-life/archive/2012/03/31/2425631.html
转载注明出处是人格的一种体现。
能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。若有满嘴喷粪撕逼者,一律拉黑、举报,并移交阎王爷处理。