java - 单例模式

java - 单例模式

  • 设计模式
  • 饿汉模式
      • 优缺点
  • 懒汉模式
      • 懒汉模式 - 简单版本
      • 懒汉模式 - 线程安全版本
      • 优缺点

这里主要介绍java中常见的单例模式的两种实现方式 1. 饿汉模式 2. 懒汉模式

设计模式

啥是设计模式?
设计模式好比象棋中的 “棋谱”. 红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有
一些固定的套路. 按照套路来走局势就不会吃亏.
软件开发中也有很多常见的 “问题场景”. 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照
这个套路来实现代码, 也不会吃亏.
而单例模式就是设计模式之一,同时也是校招面试时最容易考的设计模式之一.

饿汉模式

饿汉模式就是类加载的同时, 创建实例.

//单例模式 - 饿汉模式
class Singleton {
    // 唯一实例本体,直接就能够获取实例
    private static Singleton instance = new Singleton();
    // 获取这个类对象
    public static Singleton getInstance() {
        return instance;
    }
    // 用private 修饰构造方法可以禁止外部实例对象
    // 保证了该类的对象只能有一个
    private Singleton() {};
}

优缺点

  • 优点:饿汉模式是线程安全的.
  • 缺点:在程序启动时就将对象给创建出来了,如果后续并未使用该对象就容易造成资源的浪费.

懒汉模式

懒汉模式就是在类加载的时候不创建实例. 第一次使用的时候才创建实例.

懒汉模式 - 简单版本

// 懒汉模式 - 单例模式
// 线程不安全
class  SingletonLazy {
	// 不初始化对象
	// 需要用时在初始化
    private static SingletonLazy instance = null;
    // 调用getInstance 时才实例对象
    public static SingletonLazy getInstance() {
    	// 判断是否是第一次实例对象
       if(instance == null) {
           instance = new SingletonLazy();
       }
       return instance;
    }
    // 用private 修饰构造方法可以禁止外部实例对象
    // 保证了该类的对象只能有一个
    private SingletonLazy() { };
}
  • 问题: 上述代码在多线程情况下还能够正常使用?
  • 回答: 并不是的哟!

java - 单例模式_第1张图片

  • 解决方案:
  • 1 保证代码的原子性就能够解决问题 - 加锁(synchronized)
  • 2 解决锁竞争问题 - 双重if 判断
  • 3 解决内存可见性问题和指令重排序问题 - 加关键字: volatile

懒汉模式 - 线程安全版本

class  SingletonLazy {
    // volatile 解决指令重排序问题和内存可见性问题
    volatile private static SingletonLazy instance = null;

    public static SingletonLazy getInstance() {
        // 外层if 为了解决锁竞争问题
        // 存在指令重排序问题和内存可见性问题
        if(instance == null) {
            // 内存if 为了解决原子性
            // 存在锁竞争问题
            synchronized(SingletonLazy.class){
                if(instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private SingletonLazy() { };
}

优缺点

  • 优点:懒汉模式是在程序需要用到时才会创建实例,能够保证内存使用的空间效率提高,不会造成资源浪费
  • 缺点:在不加锁多线程的情况下,会导致线程不安全的情况(没加锁,就会导致在多线程调度同一个getInstance() 方法时出现实例了多个对象,以及锁竞争,内存可见性问题),所以实现时就需要更加注意处理条件的灵活使用(双重if判断).
  • 问题: 懒汉模式的简单版本在单线程情况下是否线程安全?
  • 回答: 是线程安全的!

你可能感兴趣的:(java,-,基础语法部分,单例模式,java,开发语言)