Java设计模式之单例模式简单解析

 更新时间:2023年12月16日 09:41:52   作者:小晨想好好学习  
这篇文章主要介绍了Java设计模式之单例模式简单解析,单例模式的优点在于在内存中某个类只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例,避免对资源的多重暂用,需要的朋友可以参考下

单例模式的优缺点

优点:

  • 在内存中某个类只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
  • 避免对资源的多重暂用

缺点: 没有接口,不能继承

单例模式的几种实现方式

1、饿汉式(线程安全)

类加载时就初始化实例,避免了多线程同步问题,天然线程安全。

为什么饿汉式是线程安全的? 类加载的方式是按需加载,且只加载一次。因此,在上述单例类被加载时,就会实例化一个对象并交给自己的引用,供系统使用,即在线程访问单例对象之前,其就已经创建好了。线程每次都只能拿到这个唯一的对象。因此,饿汉式单例天生就是线程安全的。

class Singleton{
    //1、私有化构造器,这样外部就不能通过构造器来创建对象
    private Singleton(){
    }
    //2、本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    //3、对外提供一个共有的静态方法,返回对象实例
    public static Singleton getInstance(){
        return instance;
    }
}

2、饿汉式(静态代码块方式)

class Singleton{
    //1、私有化构造器,这样外部就不能通过构造器来创建对象
    private Singleton(){
    }
    //2、本类内部创建对象实例
    private static Singleton instance;
    //3、在静态代码块中创建单例对象
    static {
        instance = new Singleton();
    }
    //4、对外提供一个共有的静态方法,返回对象实例
    public static Singleton getInstance(){
        return instance;
    }
}

3、懒汉式(线程不安全)

实例对象在第一次被调用的时候才真正构建的,而不是程序一启动就会自动构建。这种实现最大的问题就是不支持多线程,因为没有加锁 ,多线程场景下不要使用,因为可能会产生多个对象,不再是单例

class Singleton{
    private static Singleton instance;
    private Singleton(){};
    //提供一个静态的公有方法,当使用到该方法时,才会去创建instance
    public static Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

4、懒汉式+锁 实现多线程安全的单例模式

每次获取实例时,也需要等待其他线程的锁释放,效率低

class Singleton{
    private static Singleton instance;
    private Singleton(){};
    //提供一个静态的公有方法,当使用到该方法时,才会去创建instance
    public static synchronized Singleton getInstance(){
        if(instance==null){
            instance = new Singleton();
        }
        return instance;
    }
}

5、double-check locking实现单例模式

多个线程只在创建实例的时候加锁实现同步

class Singleton{
    // volatile: 轻量级的synchronized, 由它修饰的变量在发生变化后会立即刷新到主存
    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;
    }
}

【注意】instance为什么需要采⽤ volatile 关键字修饰?

instance采⽤ volatile 关键字修饰也是很有必要的,在上述代码中有下面这一句代码

instance= SingletonDCL();

其实是分为三步执⾏的:

1.为 instance 分配内存空间

2. 初始化 instance

3. 将 instance指向分配的内存地址

但是由于 JVM 具有指令重排的特性,执⾏顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致⼀个线程获得还没有初始化的实例。

例如,线程A 执⾏了 1 和3,此时线程B调⽤ getInstance() 后发现 instance不为空,因此返回instance,但此时instance还未被初始化,使⽤ volatile 可以禁⽌ JVM 的指令重排 ,保证在多线程环境下也能正常运⾏。

到此这篇关于Java设计模式之单例模式简单解析的文章就介绍到这了,更多相关Java的单例模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决Spring security5.5.7报错Encoded password does not look like BCrypt异常

    解决Spring security5.5.7报错Encoded password does

    这篇文章主要介绍了解决Spring security5.5.7出现Encoded password does not look like BCrypt异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java8中接口的新特性测试

    Java8中接口的新特性测试

    今天小编就为大家分享一篇关于Java8中接口的新特性测试,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • java蓝桥杯试题

    java蓝桥杯试题

    这篇文章主要介绍了java蓝桥杯试题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • SpringMVC文件上传的配置实例详解

    SpringMVC文件上传的配置实例详解

    本文通过实例代码给大家介绍SpringMVC文件上传的配置相关内容,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-05-05
  • springboot 中异步任务,定时任务,邮件任务详解

    springboot 中异步任务,定时任务,邮件任务详解

    这篇文章主要介绍了springboot 与异步任务,定时任务,邮件任务,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Spring TransactionalEventListener事务未提交读取不到数据的解决

    Spring TransactionalEventListener事务未提交读取不到数据的解决

    这篇文章主要介绍了Spring TransactionalEventListener事务未提交读取不到数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java中的动态代理实现代码实例

    Java中的动态代理实现代码实例

    这篇文章主要介绍了Java中的动态代理实现代码实例,jdk动态代理本质上是使用被代理对象的类加载器,通过被代理类实现的接口在运行时动态构造出代理类来增强原始类的功能的方法,需要的朋友可以参考下
    2023-12-12
  • jdk动态代理源码分析过程

    jdk动态代理源码分析过程

    这篇文章主要介绍了jkd动态代理源码分析过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • Java并发之Semaphore工具类r的全面解析

    Java并发之Semaphore工具类r的全面解析

    Semaphore 是 java.util.concurrent中非常有用的并发编程工具类,它通常被用于限制对某个资源或资源池的并发访问数量,下面我们就来深入了解一下Semaphore的具体使用吧
    2024-02-02
  • 解决Mybatis中mapper的ID冲突问题

    解决Mybatis中mapper的ID冲突问题

    这篇文章主要介绍了解决Mybatis中mapper的ID冲突问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06

最新评论