单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供全局访问点。单例模式的核心思想是限制某个类只能创建一个对象实例,并提供对该实例的全局访问。这样可以避免多个对象间的冲突和资源浪费,同时也方便了对该实例的管理和控制。
实现原理:
实现代码:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
// 私有化构造函数
}
public static Singleton getInstance() {
return instance;
}
}
上述代码中,私有化构造函数确保其他类无法直接通过new
关键字创建新的实例。通过将唯一实例声明为private static final
,并在静态代码块中进行初始化,可以保证该实例在类加载时就被创建。由于饿汉式在类加载时就创建了唯一实例,因此不存在线程安全问题。然而,饿汉式也存在以下问题:
3.不能处理异常情况:如果在创建过程中发生异常,则无法进行错误处理或恢复操作。
实现原理
实现代码:
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有化构造函数
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
上述代码中,getInstance()
方法使用了synchronized
关键字来保证线程安全。当多个线程同时调用getInstance()
方法时,只有一个线程能够进入临界区创建新的对象,其他线程则等待。
然而,懒汉式也存在以下问题:
2.双重检查锁失效:在某些情况下,双重检查锁机制可能失效导致多个对象被创建。
实现原理:在懒汉式(Lazy Initialization)的基础上增加了一次实例非空检查。
实现代码:
public class Singleton {
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;
}
}
上述代码中,使用了synchronized
关键字和volatile
关键字来保证线程安全性和可见性。当多个线程同时调用getInstance()
方法时,只有一个线程能够进入临界区创建新的对象,其他线程则等待。
双重检查锁机制可以避免每次都加锁带来的性能损耗,在第一次判断为空后才进行同步操作,提高了性能。然而,双重检查锁也存在以下问题:
需要注意的是,在Java 5及以上版本中使用volatile
关键字可以解决指令重排的问题。
实现原理:通过静态内部类来持有唯一实例,并且在需要时进行延迟初始化。
实现代码:
public class Singleton {
private Singleton() {
// 私有化构造函数
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
上述代码中,SingletonHolder 是一个私有的静态内部类,在该内部类中持有了唯一实例 INSTANCE。当调用 getInstance()
方法时,直接返回了 SingletonHolder 内的 INSTANCE 实例。
这种方式能够保证懒加载和线程安全性。因为在第一次调用 getInstance()
方法获取单例对象之前,并不会触发对于SingletonHolder 类的初始化操作;只有在真正需要获取单例对象时,才会触发 SingletonHolder 类的加载和实例化。
静态内部类方式解决了双重检查锁存在的指令重排问题,并且没有加锁操作,因此性能较高。同时也能够保证线程安全性和懒加载特性。因此,静态内部类方式是一种常用而有效的单例模式实现方式。
枚举单例(Enum Singleton)是一种简洁且安全的单例模式实现方式,它利用枚举类型的特性来保证只有一个实例存在。
实现原理:
实现代码:
public enum Singleton {
INSTANCE;
// 可以添加其他成员变量和方法
public void doSomething() {
// 单例对象的操作逻辑
}
}
上述代码中,Singleton 是一个带有唯一常量 INSTANCE 的枚举类型。通过访问 Singleton.INSTANCE
就可以获取到该唯一实例。
这种方式能够保证线程安全性、懒加载和防止反射攻击。因为在Java中,enum 类型会自动提供序列化机制、线程安全等特性,并防止通过反射创建多个对象。因此,枚举单例是一种简洁而安全的单例模式实现方式,适用于大多数场景。