这个世界上只有一个你之Java设计模式:单例模式

单例模式的要点

单例模式属于创建型模式

三个要点:

  • 某个类只能有一个实例
  • 它必须自己创建这个实例
  • 它必须自行向整个系统提供这个实例

单例模式的特点

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一的实例
  • 单例类必须给所有其他对象提供这一实例

饿汉式单例类

线程安全,实现简单
优点:没有加锁,执行效率高
缺点:类在加载的时候就初始化,浪费内存

public class Singleton {
    
    

    private final static Singleton SINGLETON = new Singleton();

    private Singleton() {
    
    

    }

    public static Singleton getInstance() {
    
    
        return SINGLETON;
    }
}

另一种实现:

public class Singleton {
    
    

    private static Singleton instance;

    static {
    
    
        instance = new Singleton();
    }

    private Singleton() {
    
    

    }

    public static Singleton getInstance() {
    
    
        return instance;
    }
}

懒汉式单例类

一:懒汉式,线程不安全

实现简单
没有加锁,在多线程情况下不安全

public class Singleton {
    
    

    private static Singleton instance;

    private Singleton() {
    
    
    }

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

二:懒汉式,线程安全

实现简单,线程安全
优点:第一次调用的时候才初始化,避免了消耗内存
缺点:加了synchronized关键字,效率低

public class Singleton {
    
    

    private static Singleton instance;

    private Singleton() {
    
    
    }

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

三:懒汉式,线程不安全

实现简单,线程不安全
做不到单例

public class Singleton {
    
    

    private static Singleton instance;

    private Singleton() {
    
    
    }

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

四:懒汉式,双检锁/双重校验锁

JDK1.5起
线程安全,实现较复杂
优点:线程安全,延迟加载,效率较高
注意:volatile关键字修饰很关键

public class Singleton {
    
    

    private static volatile Singleton instance;

    private Singleton () {
    
    
    }

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

五:懒汉式,静态内部类

优点:线程安全,延迟加载,效率较高
原理:类的静态属性只会在第一次加载类的时候初始化。在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

public class Singleton {
    
    

    private Singleton() {
    
    
    }

    private static class LazySingletonInstance {
    
    
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
    
    
        return LazySingletonInstance.instance;
    }
}

六:懒汉式,枚举

JDK1.5起
线程安全,实现简单
优点:更简洁,自动支持序列化机制,绝对防止多次实例化

public enum  Singleton {
    
    
    INSTANCE;
    public void whateverMethod() {
    
    

    }
}

总结

一般而言,不建议使用第1、2、3种,建议使用饿汉方式。只有在要明确实现 lazy loading效果时,才会使用第 5 种静态内部类方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式

猜你喜欢

转载自blog.csdn.net/qq_34365173/article/details/108175562