【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; } }
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!"); } }
Runtime经典的饿汉式
单例模式注意事项和细节说明
1) 单例模式保证了 系统内存中该类只存在一个对象,
节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),
但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)