单例模式

2019-07-22  本文已影响0人  SlowGO

Java实现单例模式的几种常用方式:

1. 饿汉式

实现最简单,缺点是没有使用时就创建,浪费内存。

public class SingletonHungry {
    private static final SingletonHungry INSTANCE = new SingletonHungry();

    private SingletonHungry() {
    }

    public static SingletonHungry getInstance() {
        return INSTANCE;
    }
}

2. 懒汉式 线程安全

获取对象时再实例化,为了保证线程安全,使用 synchronized 关键字进行同步,缺点是方法级的同步使效率较低。

public class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {
    }

    public static synchronized SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

3. 双重检验锁

为了提升懒汉式的效率,方法体上的锁去掉,先判断是否已经实例化看,如果没有,在真正创建对象时加锁,进入锁后还有一次判断,这是因为在多线程并发条件下,一个线程拿到锁执行实例化操作,其他线程等待,唤醒后,需要先判断是否已经创建完成了,防止多次创建。

public class SingletonDoubleCheck {
    private volatile static SingletonDoubleCheck singleton;

    private SingletonDoubleCheck (){}

    public static SingletonDoubleCheck getSingleton() {
        if (singleton == null) {
            synchronized (SingletonDoubleCheck.class) {
                if (singleton == null) {
                    singleton = new SingletonDoubleCheck();
                }
            }
        }
        return singleton;
    }
}

4. 静态内部类

此方式是通过类加载机制保证单例,虚拟机会保证类构造器在多线程环境下被正确的加锁、同步,如果多个线程同时去初始化一个类,只会有一个线程执行构造器,其他线程都要等待。

public class SingletonStaticInnerClass {
    private static class SingletonHolder {
        private static final SingletonStaticInnerClass INSTANCE = 
                new SingletonStaticInnerClass();
    }

    private SingletonStaticInnerClass (){}

    public static final SingletonStaticInnerClass getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5. 枚举

用法简单,还可以方式反射方式创建多个实例,是JDK1.5以后才支持的。

public enum SingletonEnum {

    Instance;
    
    private SingletonEnum() {
        System.out.println("init ... ");
    }

    public static void main(String[] args) {

        SingletonEnum b1 = SingletonEnum.Instance;
        SingletonEnum b2 = SingletonEnum.Instance;
        SingletonEnum b3 = SingletonEnum.Instance;
        
        System.out.println(b1 == b2);
        System.out.println(b1 == b3);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读