三言两语讲透Java设计模式(单例模式)

本文深入探讨了Java中的单例模式,包括五种实现方式:静态常量饿汉式、静态代码块饿汉式、普通懒汉式、同步方法懒汉式、双检锁(DCL)以及静态内部类和枚举实现。总结了各种方式的优缺点,如资源浪费、线程安全和懒加载特性。推荐使用静态内部类、双检锁和枚举方式来实现线程安全且高效的单例模式。
摘要由CSDN通过智能技术生成

单例模式应该是每个程序员最熟悉的设计模式之一了,在我们最初学习阶段的时候,应该就或多或少的听说过单例模式,指的就是系统中运行时某个类只能存在唯一的示例,为了解决资源浪费而产生的设计模式,如Hibernate中的SessionFactory,就使用了单例模式,本文将用极简的语言和丰富的示例去讲透单例模式。

Java中的单例模式,一共有五种大的实现方式,本文将饿汉式以及懒汉式分割为五种情况,分别介绍每种情况的优劣势。并且会在文章最后做出一个总结,如果不想看文章详细内容可以直接拉到最后看总结。

单例模式的核心思想就是不能让外部去调用该类的new方法,已知Java是通过构造器去创建对象的,所以第一部都是私有化构造器,避免外部使用new方式去创建对象,并且要有一个方法去返回当前对象这个唯一的示例。 懒汉式即当前类加载,就创建对象实例,饿汉式即需要的时候才会创建当前类实例,所以懒汉式会造成资源浪费,而饿汉式需要考虑如何解决多线程下的线程安全问题。

  1. 饿汉式
    1. 静态常量饿汉式
      class Singleton {
         // 私有化构造器
         private Singleton() {
         }
      
         // 创建当前类对象
         private final static Singleton instance = new Singleton();
      
         // 返回当前类实例
         public static Singleton getInstance() {
             return instance;
         }
      }
      
      缺点:不管这个对象是否需要 只要当Singleton类被实例化的时候,对象就会直接被创建,容易导致资源浪费,不推荐使用
    2. 静态代码块饿汉式
      class Singleton {
          // 私有化构造器
          private Singleton() {
          }
      
          // 静态代码块中创建对象实例
          static {
              instance = new Singleton();
          }
          // 创建当前类对象
          private static Singleton instance;
      
          // 返回当前类实例
          public static Singleton getInstance() {
              return instance;
          }
      }
      
    缺点:和上述情况一样,容易造成资源浪费,不推荐使用
  2. 懒汉式
    1. 普通懒汉式

      class Singleton {
          // 私有化构造器
          private Singleton() {
          }
      
          // 创建当前类对象
          private static Singleton instance;
      
          // 返回当前类实例
          public static Singleton getInstance() {
              // 如果当前实例为空 则创建 否则返回
              if (instance == null) {
                  System.out.println("instance为空");
                  instance = new Singleton();
              } else {
              	// 这里存在的意义是为了做一下多线程的测试 就知道创建了多少对象了
                  System.out.println("instance不为空");
              }
      
              return instance;
          }
      }
      

      缺点:普通的懒汉式会出现线程安全问题,如下图所示,只适用于单线程环境中可以使用这种方式
      在这里插入图片描述

    2. 同步方法懒汉式
      这里省略代码了,其实就是在获取实例的方法上 添加上一个同步关键字
      在这里插入图片描述
      优点:解决了线程安全问题。
      缺点:由于一旦有一个进入了方法,则其余会进行等待,有可能会导致多线程环境下的执行缓慢。

    3. 同步代码块懒汉式
      实现的方式就是将synchronized关键字从方法上 转移到if上面 实现一个代码块的同步,但是这个方法不可行,因为一旦进入了方法,这个同步就没太大意义了。不能使用。

  3. 双检锁
    class Singleton {
       // 私有化构造器
       private Singleton() {
       }
    
       // 创建当前类对象
       private static volatile Singleton instance;   // 这里一定要加volatile关键字 如果不知道这个是干嘛的 可以参考本人写的JUC文章 有介绍
    
       // 返回当前类实例
       public static synchronized Singleton getInstance() {
           // 如果当前实例为空 则创建 否则返回
           if (instance==null){
               synchronized (Singleton.class){
                   if (instance==null){
                       instance = new Singleton();
                       System.out.println("创建了一个实例");
                   }
               }
           }else{
               System.out.println("不为空");
           }
           return instance;
      }
    }
    
    优点:双重检查(双检锁)利用将当前实例同步主存的方式,实现只能有一个线程去创建对象,其余线程不会进入同步代码块等待,直接会在第一次检查被过滤掉,推荐使用。
  4. 静态内部类
    class Singleton {
        // 私有化构造器
        private Singleton() {
        }
    
        // 静态内部类中创建对象实例
        private static class SingletonInstance {
            private static final Singleton INSTANCE = new Singleton();
        }
    
    
        // 返回当前类实例
        public static Singleton getInstance() {
            return SingletonInstance.INSTANCE;
        }
    
    }
    
    优点:SingletonInstance类并不会在Singleton被加载而连带加载,调用Singleton Instance类的时候 类加载机制是线程安全的,所以实现了懒加载和线程安全 也是一种比较推荐的方式
  5. 枚举
    enum Singleton{
    INSTANCE;
    }
    
    优点:使用jdk1.5提供的枚举机制,可以很轻松的实现单例模式,不仅可以避免多线程问题,而且还可以避免反序列化创建新的对象,Effective Java中提倡使用该做法

总结:懒汉式,同步方法饿汉式,双检锁,静态内部类,枚举都可以解决线程安全问题,其中同步代码块饿汉式,无法解决多线程的问题。
根据本文中的分析可以得知 单例模式的好坏 取决于三种情况 1. 能否解决多线程安全 2.是否懒加载 3. 是否会导致多次重复加载同步方法影响效率。 综上所述,推荐使用静态内部类,双检锁,枚举这三种方式实现单例模式!


本系列文章参考韩顺平老师的设计模式编写,保证不用做盈利行为,仅作为个人笔记分享。


全面发展,一专多能!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值