【Java】【设计模式 Design Pattern】单例模式 Singleton

什么是单例模式?

顾名思义,一个类只存在唯一的一个实例

采取一定的方法保证在整个的软件系统中,对某个类

只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

 

 

1、饿汉式第一种:

- 写法简单、类加载时,完成了实例化,避免多线程同步问题

- 不能懒加载,如果一直没有使用过这个实例,就造成了内存占用的浪费,懒加载,就是说等我需要使用这个实例时,再执行初始化加载出来调用

- 可用,但是会浪费内存

- 饿汉本身已经非常形容这个静态加载的意思了,不过有没有使用这个实例,先吃了内存空间再说

public class Singleton01 {
    
    // 私有构造器
    private Singleton01 (){}
    
    // 静态固定实例
    private static final Singleton01 single = new Singleton01();

    // 提供公开的提供实例方法即可
    public static Singleton01 getInstance() {
        return single;
    }
}
简单饿汉

 

2、饿汉式第二种:

初始化过程放在了静态代码块,比上面更优先加载出来,其他一样

- 可用

public class Singleton01 {

    // 私有构造器
    private Singleton01 (){}
    
    // 声明单例实例
    private static Singleton01 instance;

    // 交给静态块加载
    static { instance = new Singleton01(); }

    // 一样的获取方法
    public static Singleton01 getInstance(){ return instance; }
}
饿汉二

 

3、懒汉式第一种

- 实现了懒加载行为,但是线程不安全,只能单线程

- 多线程如果没有进入if语句判断就会直接new新实例产生

- 禁止使用

public class Singleton {

   private Singleton (){}
   
   private static Singleton instance;
   
   // 如果instance为空 就new出来,反之直接返回
   public static Singleton getInstance(){
      if (instance == null) instance = new Singleton();
      return instance;
   }
}
懒汉一

 

4、懒汉式第二种

- 解决线程不安全的问题

- 效率太低,每次获取实例都需要执行同步

- 能用,不推荐使用

public class Singleton {

   private Singleton (){}
   
   private static Singleton instance;
   
   // 给方法加锁,同步处理化
   public static synchronized Singleton getInstance(){
      if (instance == null) instance = new Singleton();
      return instance;
   }
}
懒汉式二

 

5、懒汉式第三种

- 代码复杂,线程反而不安全

- 禁用

public class Singleton {

   private Singleton (){}
   
   private static Singleton instance;
   
   // 经过判断后枷锁实例,多线程直接跳过判断获取,还是会创建实例
   public static Singleton getInstance(){
      if (instance == null) synchronized (Singleton.class) { instance = new Singleton();}
      return instance;
   }
}
View Code

 

6、懒汉式第四种双重检查

- 解决线程安全

- 懒加载实现

- 效率较高

- 可用

public class Singleton {

   private Singleton (){}
   
   // 设置可见
   private static volatile Singleton instance;
   
   // 二次检查
   public static Singleton getInstance(){
      if (instance == null) synchronized (Singleton.class) {
         if (instance == null) instance = new Singleton();
      }
      return instance;
   }
}
懒汉三双重检查

 

7、静态内部类实例

- 采用类加载的机制实现懒加载,同时避免了线程安全的问题

- 在调用方法时才会加载内部类返回实例

- 推荐

public class Singleton {

   private Singleton (){}
   
   // 静态内部类不会重复加载,其静态属性也如此
   private static final class SingleInstanceClass{
      private static final Singleton INSTANCE = new Singleton();
   }
   
   // 返回内部类的属性实例即可
   public static Singleton getInstance(){
      return SingleInstanceClass.INSTANCE;
   }
}
静态内部类

 

8、枚举,永远的神

- JDK1.5特性

- 线程绝对安全、实现单例

- 不能被序列化重新创建

- 推荐

public enum Singleton{
   INSTANCE;
   
   public void ok(){
      System.out.println("ok!");
   }
}
Enum

 

Runtime经典的饿汉式

 

单例模式注意事项和细节说明

1) 单例模式保证了 系统内存中该类只存在一个对象,

  节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能

 

2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new

 

3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),

  但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)

 

posted @ 2020-04-17 21:22  emdzz  阅读(147)  评论(0编辑  收藏  举报