设计模式-单例模式

98 阅读1分钟

单例模式

一个类只允许创建一个对象。

为什么要使用单例

  • 处理资源访问冲突(对一个文件,同时写入日志)
  • 全局唯一类(配置数据在系统中只保留一份)

应用场景

  • 数据库连接池、日志记录类、配置读取
  • JDK中的java.lang.Runtime 该类用于管理程序运行期间的信息:memory 和 processor信息

双重检测

//饿汉式不支持延迟加载
//懒汉式并发性能不高,getInstance方法被加了synchronized

//使用双重检测式

public class Singleton{
	private static Singleton single;
	private Singleton(){}
		
		public static Singleton getInstance(){
			if(null == instance){
				synchronized(Singleton.class){
					if(null == instance) instance = new Singleton();
				}
			}
		return instance;
		}
}

指令重排序,可能会导致Singleton对象被new 出来赋值给instance后,还没来得及初始化(执行构造函数中的代码逻辑)就被另一个线程使用了,需要给instance成员变量加上volatile关键值,禁止指重排序。实际上只有低版本的jdk 才会有这个问题,高版本已经在jdk内部通过把对象new操作和初始化操作设为原子操作,解决了这个问题。

静态内部类

public class Singleton{
	private Singleton(){}

	private static class SingletonHolder{
		private static final Singleton instance = new Singleton();
	}

	public static Singleton getInstance(){
		return SingletonHolder.instance;
	}
}

当外部类被加载的时候并不会创建SingletonHolder实例,只有调用getInstance方法时,才会创建instance, instance的唯一性和创建过程中的线程安全性都是JVM来保证的。

枚举

public enum Singleton{
	INSTANCE;
	private String name;
  public String getName()
      return name;
  }
  public void setName(String name){
     this.name = name;
  }
}

通过java枚举本身的特性,保证了实例创建的线程安全性和实例的唯一性。