java单例模式常见的几种写法

Posted wen-pan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java单例模式常见的几种写法相关的知识,希望对你有一定的参考价值。

单例模式有多种写法,都有各自的优缺点,最常见的优缺点就是【懒汉和饿汉】的比较,以及是否线程安全

  • 懒汉模式,节约内存,只有使用到时才创建单例对象,可能会有线程安全问题
  • 饿汉模式,浪费内存,但可以由JVM类加载器去保证线程安全

一、饿汉模式

public class Singleton1 

    /**
     * 饿汉式提前创建好单例对象(在类被主动使用时便会触发静态变量的初始化)
     */
    private final static Singleton1 INSTANCE = new Singleton1();

    /**
     * 禁止外部实例化
     */
    private Singleton1() 

    

    public static Singleton1 getInstance() 
        return INSTANCE;
    

二、懒汉模式(线程不安全)

public class Singleton2 

    /**
     * 即使是类被主动使用,也不会触发INSTANCE的创建
     */
    private static volatile Singleton2 INSTANCE = null;

    /**
     * 禁止外部实例化
     */
    private Singleton2() 

    

    /**
     * 当调用getInstance方法获取单例对象时再创建单例对象,当INSTANCE为空时才创建
     * 这种是线程不安全的
     */
    public static Singleton2 getInstance() 
        if (INSTANCE == null) 
            INSTANCE = new Singleton2();
        
        return INSTANCE;
    

三、懒汉模式(线程安全)

public class Singleton6 

    private static volatile Singleton6 INSTANCE = null;

    /**
     * 禁止外部实例化
     */
    private Singleton6() 

    

    public static Singleton6 getInstance() 
      	// 通过加锁保证线程安全,但是性能会相应的降低
        synchronized (Singleton6.class) 
            if (INSTANCE == null) 
                INSTANCE = new Singleton6();
            
            return INSTANCE;
        
    


四、双检锁单例

public class Singleton3 

    /**
     * 注意这里需要用volatile去修饰,以避免指令重排代理的多线程安全问题
     */
    private static volatile Singleton3 INSTANCE = null;

    /**
     * 禁止外部实例化
     */
    private Singleton3() 

    

    public static Singleton3 getInstance() 
        // 两次检查,线程安全
        if (INSTANCE == null) 
            synchronized (Singleton3.class) 
                if (INSTANCE == null) 
                    INSTANCE = new Singleton3();
                
            
        
        return INSTANCE;
    


五、静态内部类写法

public class Singleton4 

    /**
     * 禁止外部实例化
     */
    private Singleton4() 

    

    public static Singleton4 getInstance() 
        // 外部内可以访问静态内部类的私有成员变量
        return Holder.instance;
    

    /**
     * 静态内部类实现单例模式,只有在Holder类被主动使用时才会触发Holder类的加载,从而触发instance的实例化,
     * 并且是由JVM去实例化的保证线程安全,所以这种模式也是线程安全的懒汉模式
     */
    static class Holder 
        /**
         * 静态内部类里持有一个Singleton4的单例对象
         */
        private static Singleton4 instance = new Singleton4();
    

六、枚举写法

public enum Singleton5 

    /**
     * 单例对象,枚举实现单例,写法就很简单了,并且能保证线程安全(枚举类是由JVM加载),但枚举是饿汉模式
     */
    INSTANCE;

    /**
     * 提供一个获取枚举对象的方法
     */
    public Singleton5 getInstance() 
        return INSTANCE;
    

以上是关于java单例模式常见的几种写法的主要内容,如果未能解决你的问题,请参考以下文章

线程安全的单例模式的几种实现

单例模式的几种常见写法

常见的几种单例模式写法

单例模式(下)---聊一聊单例模式的几种写法

单例模式的几种写法

单例模式的几种写法