单例模式详解
在设计模式中单例模式保证一个类中只有一个实例,并且提供一个全局访问点。
一般会用以下几种实现方式:
1、饿汉模式:
这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){ } public static Singleton getInstance() { return instance; } }
2、懒汉模式(线程不安全):
懒汉模式申明了一个静态对象,在用户第一次调用时初始化,虽然节约了资源,但第一次加载时需要实例化,反映稍慢一些,而且在多线程不能正常工作。
public class Singleton { private static Singleton instance; private Singleton (){ } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
3、懒汉模式(线程安全):
这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。
public class Singleton { private static Singleton instance; private Singleton (){ } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
4、双重校验锁模式:
public class singleton{ private volatitle static singleton instance; //使用volatile 表明每次都会去内存中读取最新的值; static 表明生成周期和当前应用一样 public singleton(){ } public static singleton getInstance(){ //同样使用静态方法获取 if(instance == null){ synchronized (singleton.classs){ //在多线程中获取需要进行同步,或者会导致同步问题 if(instance == null) instance = new singleton(); } } return instance; } }
5、静态内部类
这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。
public class singleton { private singleton(){ } public static singleton getInstance(){ return singletonHolder.sInstance; } private static class singletonHolder { private static final singleton sInstance = new singleton(); } }
6、枚举单例
默认枚举实例的创建是线程安全的,并且在任何情况下都是单例
public enum Singleton { INSTANCE; public void doSomeThing() { } }
上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化