单例模式(Singleton Pattern)
单例模式用于确保某个类全局只有一个实例。
单例模式的最基本的UML类图:
单例模式的最基本的代码示例:
1 public class Singleton 2 { 3 private static Singleton instance = null; 4 5 private Singleton() {}; 6 7 public static Singleton getInstance() 8 { 9 if(instance == null) 10 { 11 instance = new Singleton(); 12 } 13 return instance; 14 } 15 }
对于上面的单例模型,如果对于单线程程序来说,不会存在什么问题,但是对于多线程可能会产生多个实例,对此我们有三种不同的实现方式
1. 饿汉实现,在声明静态属性的时候进行初始化,代码示例如下:
1 public class EagerSingleton 2 { 3 private static EagerSingleton instance = new EagerSingleton(); 4 5 private EagerSingleton() {}; 6 7 public static EagerSingleton getInstance() 8 { 9 return instance; 10 } 11 }
对于这个实现在类第一次加载的时候,静态变量instance就会被初始话,保证了实例的的唯一性,不足之处,不能实现实例的延迟创建。
2. 懒汉实现,对get方法进行线程锁控制实现
1 public class LazySingleton 2 { 3 private static LazySingleton instance = null; 4 5 private LazySingleton() {}; 6 7 synchronized public static LazySingleton getInstance() 8 { 9 if(instance == null) 10 { 11 instance = new Singleton(); 12 } 13 return instance; 14 } 15 }
懒汉模式通过synchronized关键字解决了线程安全问题,也实现了实例的延迟创建,但是需要检测线程锁对于高并发环境性能会大大降到。
3. IoDH实现(Initialization on Demand Holder),通过在单例类中增加增加静态内部类来实现
1 public class IoDHSingleton 2 { 3 private static HolderClass 4 { 5 private final static IoDHSingleton instance = new IoDHSingleton(); 6 } 7 8 private IoDHSingleton() {}; 9 10 public static IoDHSingleton getInstance() 11 { 12 return HolderClass.instance; 13 } 14 }
对于这个实现既解决了线程安全问题,也实现了实例的延迟创建,但是不足之处很多面向对象语言不支持静态内部类的特性。
此外,还有双重检测锁定的方式实现,但是由于双重检测锁定的方式中的,单例属性要加volatile关键字,而volatile关键字会屏蔽java虚拟机所做的一些代码优化,和锁定代码块会影响性能,所以也不是很少的方法,所以也就不做代码实现了。
对于单例模式很多人说,单例模式长时间不用会被gc回收,我认为在Java中是不存在这种情况的,Java中单例模式创建的对象被自己类中的静态属性所引用,所以不会被回收。