java设计模式之单例模式

单例模式(singleton pattern)真的是老生常谈了。本质上就是为了节省内存开销,希望尽可能减少对象创建数量,尤其是只用来做函数调用的对象。
单例模式分两种:懒汉式和饿汉式。补充一点,不管是哪种,都应该私有化构造函数强化单例性质。
A.懒汉式
关于懒汉式我真的不想说啥,这玩意线程安全问题太多了,多到都不想去用。直接上案例:

/**
 * 懒汉式单例
 */
public class LazySingleton {
    private static LazySingleton singleton = null;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        //1
        if (singleton == null) {
            //2
            singleton = new LazySingleton();
        }
        return singleton;
    }
}

好,上述是经典错误。线程安全问题。。A线程和B线程有可能同时进入2位置。。
改进一下:

/**
 * 懒汉式单例
 */
public class LazySingleton {
    private static LazySingleton singleton = null;

    private LazySingleton() {
    }

    public synchronized static LazySingleton getInstance() {
        //1
        if (singleton == null) {
            //2
            singleton = new LazySingleton();
        }
        return singleton;
    }
}

加了线程互斥锁,以性能为代价,保证线程安全,这个没毛病。然后就有强迫症程序员要优化了

/**
 * 懒汉式单例
 */
public class LazySingleton {
    private static LazySingleton singleton = null;

    private LazySingleton() {
    }

    public  static LazySingleton getInstance() {
        synchronized (LazySingleton.class){
            //1
            if (singleton == null) {
                //2
                singleton = new LazySingleton();
            }
        }
        return singleton;
    }
}

改成了同步代码块,确实稍微好了点,但是有的童鞋还是不满意,于是有了接下来:

/**
 * 懒汉式单例
 */
public class LazySingleton {
    private static LazySingleton singleton = null;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        //0
        if (singleton == null) {
            synchronized (LazySingleton.class) {
                //1
                if (singleton == null) {
                    //2
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }
}

貌似叫啥子双重检测锁,好吧,感觉好复杂。事实上这个还是有问题。因为java的一些操作本身就不是原子性的,即对象生成和初始化分了好几步,有兴趣的童鞋可以去研究下。
然后是终极版:

/**
 * 懒汉式单例
 */
public class LazySingleton {
    private volatile static LazySingleton singleton = null;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        //0
        if (singleton == null) {
            synchronized (LazySingleton.class) {
                //1
                if (singleton == null) {
                    //2
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }
}

加了volatile关键字。。原理就不赘述了,有兴趣的童鞋可以自己查资料。。
扯远了,咱们不说那个恶心的懒汉式了。
B.饿汉式
写法很多,举个栗子:


/**
 * 饿汉式单例
 */
public class HungarySingleton {
    private static HungarySingleton singleton = new HungarySingleton();

    public static HungarySingleton getInstance() {
        return singleton;
    }
    private HungarySingleton() {
    }

}

当然有人把声明和初始化分开的,都无所谓,用的是类加载线程互斥的原理。
接下来说一个最好的饿汉式单例实现:

/**
 * 饿汉式单例
 */
public enum HungarySingleton {
    singleton
}

单枚举的枚举类,最佳实现,没有之一

总结:
(1)单例主要是为了节省内存开销
(2)如果没有啥特殊要求,就用饿汉式吧。。。

你可能感兴趣的:(设计模式,java设计模式,java)