单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
范围:一个虚拟机范围
本质:控制实例数目
主要实现: 懒汉式(延迟加载)、饿汉式
具体实现步骤:

  1. 构造方法私有化
  2. 提供获取实例的方法
  3. 把获取实例的方法变成静态的
  4. 定义存储实例的属性
  5. 把这个属性也定义成静态的
  6. 实现控制实例的创建getInstance()
  7. 完整的实现

二者不同在于如何实现getInstance方法
优缺点:

  • 时间和空间
    懒汉式是典型的时间换空间
    饿汉式是典型的空间换时间
  • 线程安全
    不加同步的懒汉式是线程不安全的
    饿汉式是线程安全的
    利用synchronize实现懒汉式线程安全
    使用“双重检查加锁”既可以实现线程安全,又能够使性能不受到很大的影响

更好的单例实现方式:Lazy initialization holder class模式,这个模式综合使用了java的类级内部类和多线程缺省同步锁的知识
以下为单例的几种主要实现方式:
饿汉式

/**
 * 饿汉式实现单例模式,线程安全
 * @author hxp
 * 2019年3月13日 下午11:04:03
 */
public class Singleton1 {
    private static Singleton1 singleton = new Singleton1();
    
    private Singleton1() {}

    public static Singleton1 getInstance() {
        return singleton;
    }
}

懒汉式

/**
 * 懒汉式实现单例模式,getInstance加上synchronized确保线程安全
 * @author hxp
 * 2019年3月13日 下午11:04:03
 */
public class Singleton2 {
    private static Singleton2 singleton;
    
    private  Singleton2() {}

    public static synchronized Singleton2 getInstance() {
        if(null == singleton) {
            singleton = new Singleton2();
        }
        return singleton;
    }
}

双重检查锁机制

/**
 * 双重检查锁机制实现单例模式
 * @author hxp
 * 2019年3月13日 下午11:04:03
 */
public class Singleton3 {
    private static Singleton3 singleton;
    
    private  Singleton3() {}

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

静态内部类

/**
 * 静态内部类实现单例模式
 * @author hxp
 * 2019年3月13日 下午11:04:03
 */
public class Singleton4 {
    private  Singleton4() {}
    private static class SingletonStaticInnerClass {
        private static final Singleton4 instance = new  Singleton4();
    }
    public static  Singleton4 getInstance() {
        return SingletonStaticInnerClass.instance;
    }
}

枚举类

/**
 * 枚举类实现单例模式
 * @author hxp
 * 2019年3月13日 下午11:04:03
 */
public enum Singleton5 {
    INSTANCE;//枚举元素即单例
    //相对应操作
    public void doSomething() {        
    }
}

在实现时可以根据对应的单例实例占用资源的多少、是否需要延迟加载进行选择不同的方式,当占用资源少,不需要延时加载的时候,枚举类好于饿汉式,当占用资源多,需要延时加载,静态内部类好于懒汉式。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐