定义:
保证一个类只有一个实例,并提供一个访问它的全局访问点。
实现:
1. 将构造方法私有化。外部不能通过构造方法来实例化一个对象,只能通过静态方法来获得该类的唯一实例。
2. 定义一个私有类的静态变量。(静态方法不能访问非静态成员变量,所以定义一个静态变量)
3. 提供一个共有的获取实例的静态方法。
好处:
单例模式的特点是单例类在应用程序中只被实例化一次,以保证外界访问的都是同一个对象。避免了多次创建的问题,节省系统资源,加快对象的访问速度。
缺点:
不适于变化的对象,没有抽象层不利于扩展。
五种书写单例模式方式:
- 懒汉式
在第一次使用时候才进行初始化,有线程安全问题,达到懒加载效果。 添加关键字 synchronized 保证线程安全。防止多线程中A和B同时进入instance没有初始化 创建两个实例。每次获取实例都要进行同步,因此效率低。
public class Singleton01 { // 定义一个私有类的静态变量 private static Singleton01 instance; // 私有化构造函数 private Singleton01() {} // 提供一个共有的获取实例的静态方法 public static synchronized Singleton01 getInstance() { if (instance == null) { instance = new Singleton01(); } return instance; } }
总结:线程安全(添加了synchronized 关键字) 、 懒加载 (执行时才初始化)、效率低(每次都要进行同步)
- 饿汉式
加载时候就初始化,没有线程安全问题,效率高、没有懒加载,如果该实例没有被使用过,会造成内存浪费。
public class Singleton02 { // 定义一个私有类的静态变量并初始化 private static Singleton02 instance = new Singleton02(); // 私有化构造函数 private Singleton02() {} // 提供一个共有的获取实例的静态方法 public static Singleton02 getInstance() { return instance; } }
总结:线程安全(不存在线程问题)、非懒加载、 效率高
- 双重监测机制(DCL)
只有使用时,才进行初始化,达到懒加载效果、只有在初始化时候才会进行加锁、没有线程问题、也不会影响效率。
public class Singleton03 { // volatile 使每次使用都从主存中取而不是工作内存中获取 private static volatile Singleton03 instance; // 私有化构造函数 private Singleton03() {}; // 提供一个共有的获取实例的静态方法 public static Singleton03 getInstance() { if(instance == null) { // 如果instance等于空 则同步(加锁) // 只能有一个线程得到资源执行。另一个线程等待当前线程执行完才能执行该代码块。 // 只有初始化的时候为空 所有只加锁一次 synchronized (Singleton03.class) { // 第二次进行判断 if(instance == null) { instance = new Singleton03(); } } } return instance; } }
总结:线程安全(初始化时加锁)、懒加载、效率高
- 静态内部类(延迟初始化占位类)
只有使用时候,调用静态内部类进行初始化、达到懒加载效果。没有线程问题(类变量的赋值语句,在编译生成字节码的时候写在<clinit>()中,初始化单线程调用<clinit>()完成变量的赋值)、效率高。
public class Singleton04 { // 定义一个静态内部类用来初始化静态变量 private static class SingletonHolder{ private static final Singleton04 instance = new Singleton04(); } // 私有化构造函数 private Singleton04() {} // 提供一个共有的获取实例的静态方法 public static Singleton04 getInstance() { return SingletonHolder.instance; } }
总结:线程安全、懒加载、效率高
- 枚举
枚举线程安全只会装载一次,线程安全。不会被反射破坏单利。
public class Singleton05 { // 私有化构造函数 private Singleton05() {}; // 枚举类型 private enum SingletonEnum{ INSTANCE; // 私有化成员变量 private final Singleton05 instance; // 构造函数 SingletonEnum(){ instance = new Singleton05(); } // 私有化方法 private Singleton05 getInstance() { return instance; } } // 提供一个共有的获取实例的静态方法 public static Singleton05 getInstance() { return SingletonEnum.INSTANCE.getInstance(); } }
总结:线程安全、懒加载、效率高