单例模式应该大家都学习过。单一个对象需要被频繁使用,使用单例模式,可以节省创建对象消耗的时间,也能节省内存。下面介绍几种单例的创建方法,和性能对比。
(1)普通方式,私有化构造函数,使用静态变量进行初始化,在类被加载的时候初始化
class Singleton { private static Singleton instance = new Singleton(); private Singleton() { System.out.println("Singleton is create"); } public static Singleton getInstance() { return instance; } public static void createString() { System.out.println("createString in Singleton"); } }
(2)延迟加载的单例模式(懒汉模式),当第一次调用的时候,初始化实例,需使用同步机制,保证线程安全
class LazySingleton { private LazySingleton() { System.out.println("LazySingleton is create"); } private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if(instance == null) { instance = new LazySingleton(); } return instance; } }
(3)使用内部静态内部类的单例模式,使用内部类,让jvm虚拟机,直接保证线程安全,该方法优于(2)
class StaticSingleton { private StaticSingleton() { System.out.println("StaticSingleton is create"); } private static class SingletonHolder { private static StaticSingleton instance = new StaticSingleton(); } public static StaticSingleton getInstance() { return SingletonHolder.instance; } public static void createString() { System.out.println("createString in Singleton"); } }
(4)对比(1)(2)(3)三种模式的单例模式性能
import java.io.*; public class SingletonTest { public static void main(String[] args) { StaticSingleton.createString(); long time = System.currentTimeMillis(); System.out.println("time is "+time); int max = 1000000; for(int i = 0; i < max;i++) { Singleton.getInstance(); } System.out.println("spend :"+(System.currentTimeMillis() - time)); time = System.currentTimeMillis(); for(int i = 0; i < max;i++) { LazySingleton.getInstance(); } System.out.println("spend :"+(System.currentTimeMillis() - time)); time = System.currentTimeMillis(); for(int i = 0; i < max;i++) { StaticSingleton.getInstance(); } System.out.println("spend :"+(System.currentTimeMillis() - time)); }
结果如下:
有此可见,性能(1)(3),优于(2),当我们需要延长加载时(加快启动速度),可以使用(3)来替代(2)。
(5)进阶,在有对象被序列化,如何保证单例模式的对象唯一? 答案就是重写readResolve()方法。具体代码如下
class SerSingleton implements Serializable { String name; private SerSingleton() { System.out.println("Singleton is create"); name = "SerSingleton"; } private static SerSingleton instance = new SerSingleton(); public static SerSingleton getInstance() { return instance; } public static void createString() { System.out.println("createString in Singleton"); } private Object readResolve() { //阻止新生成的新实例,总是返回当前对象 return instance; } }