单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在Java中,单例模式的实现需要考虑线程安全问题,特别是在多线程环境下。
饿汉式在类加载时就完成了实例化,因此是线程安全的。但由于无论是否使用实例,它都会在类加载时创建,可能会造成资源浪费。
public class SingletonEager {
private static final SingletonEager INSTANCE = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}
懒汉式在第一次使用时才创建实例,节省资源。但基本的懒汉式在多线程环境下是不安全的。
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
通过在方法上添加`synchronized`关键字,可以确保线程安全,但性能较差。
public class SingletonLazyThreadSafe {
private static SingletonLazyThreadSafe instance;
private SingletonLazyThreadSafe() {}
public static synchronized SingletonLazyThreadSafe getInstance() {
if (instance == null) {
instance = new SingletonLazyThreadSafe();
}
return instance;
}
}
双重检查锁定既保证了线程安全,又提高了性能。它首先检查实例是否为空,如果不为空则直接返回;如果为空则进入同步块,再次检查实例是否为空,然后创建实例。
public class SingletonDoubleCheckedLocking {
private static volatile SingletonDoubleCheckedLocking instance;
private SingletonDoubleCheckedLocking() {}
public static SingletonDoubleCheckedLocking getInstance() {
if (instance == null) {
synchronized (SingletonDoubleCheckedLocking.class) {
if (instance == null) {
instance = new SingletonDoubleCheckedLocking();
}
}
}
return instance;
}
}
在双重检查锁定中,`volatile`关键字确保多个线程正确处理单例变量`instance`的可见性。`volatile`禁止指令重排序优化,从而确保在多线程环境下创建单例实例的正确性。
这种方式利用了类加载机制来保证线程安全,同时实现了延迟加载。由于静态内部类只有在外部类被调用时才会加载,因此这种方式既高效又安全。
public class SingletonBillPugh {
private SingletonBillPugh() {}
private static class Holder {
private static final SingletonBillPugh INSTANCE = new SingletonBillPugh();
}
public static SingletonBillPugh getInstance() {
return Holder.INSTANCE;
}
}
枚举是实现单例模式的最佳方式,因为它天生防止反序列化重新创建新的对象,并且由JVM保证线程安全。
public enum SingletonEnum {
INSTANCE;
// 其他方法
public void someMethod() {
// 实现方法
}
}
在Java中,单例模式的实现方式有多种,每种方式都有其优缺点。在多线程环境下,需要特别注意线程安全问题。通过合理使用`volatile`关键字、静态内部类以及枚举等方式,可以有效地实现线程安全的单例模式。