单例模式
饿汉式单例
饿汉式单例在类加载时就创建实例,因此是线程安全的。
public class EagerSingleton{
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton(){
//私有构造器
}
public static EagerSingleton getInstance(){
return INSTANCE;
}
}
懒汉式单例
懒汉式单例在第一次调用getInstance方法时创建实例。这种方式不是线程安全的。在多线程环境下,如果多个线程同时访问getInstance方法并且instance为null,那么多个线程可能会同时通过if (instance == null)这个检查,导致多个线程同时创建实例,这就违反了单例模式的初衷,导致创建了多个实例。
public class LazySingleton{
private static LazySingleton instance;
private LazySingleton(){
//私有构造器
}
//多线程下,由于多个线程访问
public static LazySingleton getInstance(){
if(instance ==null){
instance = new LazySingleton();
}
return instance;
}
}
线程安全的懒汉式单例
通过同步getInstance方法来确保线程安全,但这种方式性能较差,因为每次访问都需要同步。
public class SynchronizedLazySingleton{
private static SynchronizedLazySingleton instance;
private SynchronizedLazySingleton(){
//私有构造器
}
public static synchronized SynchronizedLazySingleton getInstance(){
if (instance == null) {
instance = new SynchronizedLazySingleton();
}
return instance;
}
}
双重检查锁
使用双重检查锁机制来确保线程安全,同时提高性能。
public class DoubleCheckedLockingSingleton{
//使用volatile关键字
private static volatile DoubleCheckedLockingSingleton instance;
private DoubleCheckedLockingSingleton(){
//私有构造器
}
public static DoubleCheckedLockingSingleton getInstance(){
if(instance == null){
synchronized(DoubleCheckedLockingSingleton.class){
if(instance ==null){
instance = new DoubleCheckedLockingSingleton();
}
}
}
return instance;
}
}
静态内部类
Java虚拟机在加载外部类时,并不会立即加载静态内部类,只有在第一次访问静态内部类的成员时,才会加载该内部类。由于类加载过程是线程安全的,JVM会保证一个类的<clinit>()方法在多线程环境下被正确地加锁和同步。
public class BillPughSingle{
private BillPughSingleton() {
// 私有构造器
}
//使用静态内部类
private static class SingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return SingletonHelper.INSTANCE;
}
}