单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在Java中实现单例模式时,考虑到多线程环境下的线程安全问题,有以下五种常见的线程安全写法。
一、饿汉式(静态常量)
饿汉式是在类加载时就完成实例化,一旦类加载,实例就会存在。
public class Singleton {
// 静态常量,直接实例化
private static final Singleton INSTANCE = new Singleton();
// 私有构造方法,防止外部直接创建实例
private Singleton() {}
// 提供公共的静态方法,返回实例
public static Singleton getInstance() {
return INSTANCE;
}
}
这种方式的优点是实现简单,缺点是在类加载时就初始化,可能会消耗更多资源。
二、懒汉式(线程不安全)
懒汉式是在需要使用时才进行实例化,但是没有考虑线程安全。
public class Singleton {
// 实例变量,初始为null
private static Singleton INSTANCE = null;
// 私有构造方法,防止外部直接创建实例
private Singleton() {}
// 提供公共的静态方法,返回实例
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
这种方式的优点是实现简单,缺点是存在线程安全问题。
三、懒汉式(双重校验锁)
双重校验锁通过加锁和条件检查来保证只有一个实例被创建。
public class Singleton {
// 实例变量,初始为null
private static volatile Singleton INSTANCE = null;
// 私有构造方法,防止外部直接创建实例
private Singleton() {}
// 提供公共的静态方法,返回实例
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
这种方式的优点是兼顾了延迟加载和线程安全。
四、静态内部类
静态内部类可以在类加载时不加载单例实例,在需要使用时才加载,符合懒加载原则。
public class Singleton {
// 私有构造方法,防止外部直接创建实例
private Singleton() {}
// 静态内部类
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 提供公共的静态方法,返回实例
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
这种方式的优点是延迟加载,同时保证线程安全。
五、枚举实现
使用枚举实现单例是最佳实践,它既保证了线程安全,也防止了反射和反序列化的攻击。
public enum Singleton {
// 枚举元素本身就是单例
INSTANCE;
public void someMethod() {
// 实现方法
}
}
这种方式的优点是实现简单,同时提供了序列化和反射攻击的防护。
总结,以上就是Java中常见的五种线程安全的单例模式写法。在实际应用中,应根据具体需求选择合适的实现方式。
