懒汉模式实现单例
public class singleMode { private static singleMode sing = null; private singleMode () { /** * 必须私有化构造方法,避免外部创建新对象 */ } public static singleMode getSing() { /** * 线程不安全,可能会多个线程进入if语句创建出新对象,解决方法加synchronized同步新建对象操作 */ if (sing == null) sing = new singleMode(); return sing; } }
懒汉模式实现单例加同步模块
class singleMode1 { /** * 懒汉模式实现单例加同步模块 */ private static singleMode1 sing = null; private singleMode1 () { /** * 必须私有化构造方法,避免外部创建新对象 */ } public static singleMode1 getSing() { /** * 此时解决了同步问题但是可能会导致对象溢出 * JVM在创建对象时会执行三个操作: * 1.为对象分配空间 * 2.初始化对象 * 3.设置instance指向第一步创建的空间 * 但是JVM和CPU在实际创建对象时可能对上面的步骤进行重排序,使该步骤变成1,3,2 * 这就有可能使在一个线程还没有初始化对象时对象就已经不为null了,这时别的线程在调用getsing()函数时会直接返回一个还没有初始化好的对象 * 解决方法,使用volatile修饰该引用,禁止创建对象时重排序,保证每次调用的sing都是最新值 */ if (sing == null) synchronized (singleMode1.class) { if (sing == null) sing = new singleMode1(); } return sing; } }
懒汉模式正确写法
class singleMode2 { /** * 懒汉模式正确写法 * 懒汉模式缺点,使用synchronized同步代码块,降低了多线程时的并发效率 */ private volatile static singleMode2 sing = null; // 加volatile禁止创建对象时重排序 private singleMode2 () { } public static singleMode2 getSing() { if (sing == null) synchronized (singleMode1.class) { // 加双重验证同步代码块 if (sing == null) sing = new singleMode2(); } return sing; } }
饿汉模式
class singleMode3 { /** * 饿汉模式 * 缺点:在没有初始化单例时,占用不必要的内存 */ private static singleMode3 sing = new singleMode3(); // 线程安全,无论创建多少对象,静态变量只会初始化一次 private singleMode3() { } // 静态的工厂方法 public static singleMode3 getSing() { return sing; } }
枚举模式,最安全,推荐使用
class singleMode4 { /** * 枚举模式,最安全,推荐使用 */ private singleMode4() { } public static singleMode4 getSing() { return Singleton.INSTANCE.getSing(); } private enum Singleton { INSTANCE; private singleMode4 sing; // JVM保证次构造方法只会执行一次,且在getSing调用之前会被初始化 Singleton (){ sing = new singleMode4(); } public singleMode4 getSing() { return sing; } } }