单例模式

2020-05-01  本文已影响0人  养一只tom猫

懒汉式双重检查方式

class LazySingletonTest {
    private static volatile LazySingletonTest lazySingletonTest;

    private LazySingletonTest() {

    }

    public static LazySingletonTest getInstance() {
        if (lazySingletonTest == null) {
            synchronized (LazySingletonTest.class) {
                if (lazySingletonTest == null)
                    lazySingletonTest = new LazySingletonTest();
            }
        }
        return lazySingletonTest;
    }
}

这种方式是通过双重检查+synchronized实现线程安全。
volatile:防止jvm指令重排
如果没有加volatile,那么当线程1在进行实例化时,线程2刚好执行到第一层if时,发现实例不为null,但是实例并没有真正初始化完成,那么就会出现空指针。

懒汉式静态内部类方式

class LazySingletonTest2{
    static class InnerClass{
        private static LazySingletonTest2 lazySingletonTest2 = new LazySingletonTest2();
    }

    private LazySingletonTest2(){}

    public static LazySingletonTest2 getInstance(){
        return InnerClass.lazySingletonTest2;
    }
}

这种方式是借助jvm类加载机制保证线程安全。但是如果通过反射获取该类的构造,通过构造获取对象,再通过静态方法获取对象,则会出现多个实例,不过也很好解决,在构造方法中加一层判断即可。

class LazySingletonTest2{
    static class InnerClass{
        private static LazySingletonTest2 lazySingletonTest2 = new LazySingletonTest2();
    }

    private LazySingletonTest2(){
        if (InnerClass.lazySingletonTest2 != null)
            throw new RuntimeException("不允许创建多个实例");
    }

    public static LazySingletonTest2 getInstance(){
        return InnerClass.lazySingletonTest2;
    }
}

饿汉式:

/**
 *这种方式最简单
 * 饿汉式1:这种方式是在类加载时,就创建了对象,如果你没有使用到这个对象可能造成内存浪费。
 */
public class SingletonTest1 {
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance==instance2);
    }
}

class Singleton{
    private Singleton(){}//私有构造防止new
    private final static Singleton instance = new Singleton();
    public static Singleton getInstance(){
        return instance;
    }
}
class Singleton1{
    private Singleton1(){}//私有构造防止new
    private static Singleton1 instance;
    
    static {
        instance = new Singleton1();
    }
    public static Singleton1 getInstance(){
        return instance;
    }
}
//和上面一模一样,不过是放在静态代码块实例化而已

枚举实现单例:

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanContainer {
    public BeanContainer getInstance() {
        return BeanContainerHolder.Holder.instance;
    }

    private enum BeanContainerHolder{
        /**
         * 存放单例实例
         */
        Holder;
        private BeanContainer instance;
        BeanContainerHolder() {
            this.instance = new BeanContainer();
        }
    }
}

Java源码中的单例模式


image.png
上一篇下一篇

猜你喜欢

热点阅读