美文网首页
二、单例模式

二、单例模式

作者: RainySpring | 来源:发表于2020-05-08 23:38 被阅读0次

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

  • 设计方式

1. 饿汉式方式

public class Student5 {
 // 构造私有
 private Student5() {}
 //内部创建好实例对象
 private static Student5 student = new Student5();

 /* 获取实例 */
 public static Student5 getSingletonInstance() {
   return SingletonFactory.student;
 }
}

2. 懒加载方式

1、双重检测锁解决线程安全问题

public class Student5 {
 private Student5() {}
 //需要的时候创建
 private static Student5 student = null;

 /* 获取实例 */
 public static Student5 getSingletonInstance() {
   if(student ==null){
     student = new Student();
   }
   return student;
 }
 // 构造私有
 private Student1() {}
}

懒加载的好处毋庸置疑,就是需要的时候才创建对象,不需要就不会创建,相对节省内存空间,但是也消耗了一定性能。这里还存在线程安全问题,可以使用双重检测锁去解决问题:

//这里加volatile关键作用是为了防止指令重排序
private static volatile DoubleCheckedLock instance;

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

2、内部类利用jvm保证线程安全问题
其实也可以使用jvm来保证其线程安全,而懒加载的机制则是依靠虚拟机规范制度的类“初始化”规则保证,这里可以参考下这篇文章:https://www.cnblogs.com/niuyourou/p/11892617.html

public class Singleton {
    private static class SingletonHolder {
        private static Singleton singleton = new Singleton();
    }

    private Singleton() {
    }

    public static Singleton newInstance() {
        return SingletonHolder.singleton;
    }
}

设计单例模式需要注意的问题:

1、饿汉式的线程安全问题;volatile防指令重排序问题
2、构造方法私有
3、反射攻击或者反序列化攻击

// 1、反射攻击
// 返回false,违背了单例模式的原则!!!
public static void main(String[] args) throws Exception {
    Singleton singleton = Singleton.getInstance();
    Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    Singleton newSingleton = constructor.newInstance();
    System.out.println(singleton == newSingleton);
}
// 2、反序列化攻击
//引入序列化工具包依赖
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.8.1</version>
</dependency>
//单例类实现java.io.Serializable接口,经过序列化和反序列化后引用变了,返回false
 public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        byte[] serialize = SerializationUtils.serialize(instance);
        Singleton newInstance = SerializationUtils.deserialize(serialize);
        System.out.println(instance == newInstance);
    }

解决问题的办法:枚举天生保证序列化单例
针对以上问题,单例的枚举实现在《Effective Java》中有提到,因为其功能完整、使用简洁、无偿地提供了序列化机制、在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点,单元素的枚举类型被作者认为是实现Singleton的最佳方法。

public enum DataSourceEnum {
  DATASOURCE;
  private DBConnection connection = null;
  private DataSourceEnum() {
      connection = new DBConnection();
  }
  public DBConnection getConnection() {
      return connection;
  }
}  

相关文章

  • 单例模式

    一、单例模式介绍 二、单例模式代码实例

  • 单例模式

    一、实现单例模式 或者 二、透明的单例模式 三、用代理实现单例模式 四、JavaScript中的单例模式 在Jav...

  • OC - 单例模式

    导读: 一、什么是单例模式 二、单例的作用 三、常见的单例类 四、自定义单例类的方法 一、什么是单例模式 单例模式...

  • 设计模式-iOS常见

    一、单例模式 系统的单例模式(Singleton Pattern) 二、中介者模式 中介者模式(Mediator ...

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • 单例模式

    一、定义 单例模式:单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。 二、单例模式结构...

  • Python 面向对象7: 单例模式

    一、内容 1.1、单例设计模式 1.2、__new__方法 1.3、Python 中的单例 二、单例设计模式 2....

  • 单例模式

    一、介绍 二、单例模式代码实现 三、单例的简介写法

  • Swift单例模式

    1.第一种单例模式 2.第二种单例模式

网友评论

      本文标题:二、单例模式

      本文链接:https://www.haomeiwen.com/subject/rdrcnhtx.html