单例模式应该大家都学习过。单一个对象需要被频繁使用,使用单例模式,可以节省创建对象消耗的时间,也能节省内存。下面介绍几种单例的创建方法,和性能对比。
(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;
}
}