单例模式是一种对象创建模式,用于生产对象的具体实例,并确保系统中一个类只产生一个实例。Spring中的Bean就实现了单例模式。
好处:
1)、频繁使用的对象可以节省对象创建花费的时间;
2)、new次数减少,减少对系统内存的使用频率,减轻GC压力,缩短GC停顿时间。
参与者:
1)、单例类,提供单例的工厂,返回单例
2)、使用者,获取并使用单例类。
基本构成:
1)、必须将构造方法私有化,使类外部不能被实例化。
2)、类私有的单例对象和获取对象实例的方法必须为静态的。
简单的单例实现:
public class Singleton{
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
上面实现有两个缺陷:
1)、对象创建为延迟加载,当JVM加载单例类时,即被创建。即使没有调用获取单例对象的方法。
2)、不支持多线程,在多线程环境下可能创建出多个对象。
可以通过以下两种方式优化:
1)、使用内部类实现
public class Singleton{
private Singleton(){}
private static class SingletonHolder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
2)、使用synchronized关键字
public class Singleton{
private Singleton(){}
private static Singleton instance;
public static Singleton getInstance(){
if(instance!=null){
return instance;
}else{
synchronized(Singleton.class){
if(instance==null) instance = new Singleton();
}
}
return instance;
}
}
以上两种优化方式在一般情况下都适用。不过如果在代码中利用反射机制强行调用单例类的私有化构造方法,还是会创建多个类。这种情况很少就不做处理了。
单例类的序列化和反序列化,必须加上
private Object readResolve(){
return instance;
}
否则反序列化得到的对象会与序列化前的对象不相等。