饥饿模式:直接初始化,性能问题,如果对象很大,没有使用之前就加载到内存是一种很大的浪费
public final class EagerSingleton
• {
• private static EagerSingleton singObj = new EagerSingleton();
•
• private EagerSingleton(){
• }
•
• public static EagerSingleton getSingleInstance(){
• return singObj;
• }
• }
懒汉模式(延迟加载):不可用。
保证了没有使用之前不会加载;但是线程不安全,可能会多线程同时进行初始化。
public final class LazySingleton
• {
• private static LazySingleton singObj =null;
•
• private LazySingleton(){
• }
•
• public static LazySingleton getSingleInstance(){
• if(null == singObj ) singObj = new LazySingleton();
• return singObj;
• }
• }
在初始化方法前面加线程同步Synchronized:不推荐使用。
代价是同步的大家必然会一定程度的降低并发度,影响效率,
public final class ThreadSafeSingleton
• {
• private static ThreadSafeSingleton singObj = null;
•
• private ThreadSafeSingleton(){
• }
•
• public static synchronized ThreadSafeSingleton getSingleInstance(){
• if(null == singObj ) singObj = new ThreadSafeSingleton();
• return singObj;
• }
• }
双重检查锁(降低同步的粒度,只在初始化对象时候进行进行同步):这其实一种反面模式,不推荐使用。
假设线程A执行到了第十九行,判断对象为空,于是线程A执行到第二十二行初始化这个对象,但是初始化是需要耗费时间的,但是这个对象的地址已经存在了。
此时线程B也执行到第十九行,他判断不为空,于是直接跳到第二十六行获取这个对象,但是,这个对象还没有被完整的初始化!获取了一个没有初始化完全的对象,这时就出问题了。
public final class DoubleCheckedSingleton
• {
• private static DoubleCheckedSingletonsingObj = null;
•
• private DoubleCheckedSingleton(){
• }
•
• public static DoubleCheckedSingleton getSingleInstance(){
• if(null == singObj ) {
• synchronized(DoubleCheckedSingleton.class){
• if(null == singObj)
• singObj = new DoubleCheckedSingleton();
• }
• }
• return singObj;
• }
• }
静态内部类,和饿汉式机制类似,但又有懒加载的作用。静态内部类在类被装在时并不会立即实例化,而是在需要实例化时,也即是调用getInstance()方法时,才会装载,从而完成实例化。
优先使用这种,类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
public class _6StaticInnerClassSingleton {
private static class SingletonInstance{
private static final _6StaticInnerClassSingleton INSTANCE = new _6StaticInnerClassSingleton();
}
private _6StaticInnerClassSingleton(){}
public static _6StaticInnerClassSingleton getInstance(){
return SingletonInstance.INSTANCE;
}
}