设计优化(1)单例模式

来源:互联网 发布:杭州小知科技 知乎 编辑:程序博客网 时间:2024/05/01 15:51

使用单例模式可以省略创建对象所花费的时间,而且由于new操作的次数减少,因而对系统内存使用频率降低,减轻了GC的压力,缩短了GC的停顿时间。

public class Singleton {private Singleton(){System.out.println("Singleton is creating");}private static StaticSingleton instance=new StaticSingleton();public static  StaticSingleton getInstance(){return instance;}}

然而上诉单例模式可能会问题:instance是在static中定义的,因此在JVM加载单例类的时候,单例对象就会被建立,但这个单例类有可能还会有其他方法,在使用其他方法时加载此单例类也会创建单例对象,这是不愿意见到的。因此引入了延迟加载机制:

public class LazySingleton {private LazySingleton(){System.out.println("Singleton is creating");}private static LazySingleton instance=null;public static synchronized LazySingleton getInstance(){if(instance==null){instance=new LazySingleton();}return instance;}}


可以看到,初始化单例是在同步方法中进行的,同步是为了避免多线程访问时创建多个单例对象,比如一个线程刚判断了instance==null,还在创建单例时,另一个线程可能也判断instance==null,也开始创建单例。但这样引入了新的问题,同步关键字的耗时远远高于第一种单例模式。

因此引入了一种新的方法:通过内部类维护单例:

public class StaticSingleton {private StaticSingleton(){System.out.println("Singleton is creating");}private static class SingletonHolder{private static StaticSingleton instance=new StaticSingleton();}public static  StaticSingleton getInstance(){return SingletonHolder.instance;}}


因为内部类在StaticSingleton 被加载时时不会被初始化的,只有在getInstance()方法被调用的时候,才回加载内部类,从而初始化instance。

另外,如果单例类实现了java.io.Serializabel,则在序列化和反序列化后会生成多个对象实例,此时,需要在类中实现readResolve()方法。



0 0
原创粉丝点击