单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在多线程环境中实现单例模式时,需要特别考虑线程安全问题。本文将详细介绍几种在多线程环境下实现单例模式的方法,并探讨其优化策略。
饿汉式在类加载时就创建实例,因此是线程安全的。但其缺点是无论是否需要使用实例,它都会占用内存。
public class SingletonEager {
private static final SingletonEager INSTANCE = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}
懒汉式在需要时才创建实例,但在多线程环境下存在线程安全问题。
public class SingletonLazyUnsafe {
private static SingletonLazyUnsafe instance;
private SingletonLazyUnsafe() {}
public static SingletonLazyUnsafe getInstance() {
if (instance == null) {
instance = new SingletonLazyUnsafe();
}
return instance;
}
}
通过在方法上添加`synchronized`关键字,确保每次调用`getInstance`方法时都是线程安全的,但性能较差。
public class SingletonLazySafeMethod {
private static SingletonLazySafeMethod instance;
private SingletonLazySafeMethod() {}
public static synchronized SingletonLazySafeMethod getInstance() {
if (instance == null) {
instance = new SingletonLazySafeMethod();
}
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;
}
}
利用Java的静态内部类特性实现单例模式,不仅线程安全,而且延迟加载。这是实现单例模式的最佳方式之一。
public class SingletonStaticInnerClass {
private SingletonStaticInnerClass() {}
private static class Holder {
private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();
}
public static SingletonStaticInnerClass getInstance() {
return Holder.INSTANCE;
}
}
在多线程环境下实现单例模式时,需要权衡线程安全性和性能。饿汉式适用于对实例创建时间无特殊要求且内存充足的场景;懒汉式(方法同步)虽然简单但性能较差;双重检查锁定和静态内部类则是线程安全且性能较好的选择,其中静态内部类更是推荐的实现方式。