单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。以下是几种不同的单例模式实现方法,在Java语言中的示例代码:
1. 饿汉式
这种实现方式在类加载时就立即初始化单例对象,因此称为饿汉式。它是线程安全的,因为Java保证了一个类的初始化过程是原子的。
public class SingletonHungry {
private static final SingletonHungry INSTANCE = new SingletonHungry();
private SingletonHungry() {
}
public static SingletonHungry getInstance() {
return INSTANCE;
}
}
2. 懒汉式(非同步方法)
懒汉式单例在第一次被使用时才会创建实例。这种方式简单,但是线程不安全的,在多线程环境下需要额外的同步措施来保证线程安全。
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
3. 懒汉式(同步方法)
通过将获取实例的方法声明为同步方法,可以保证在多线程环境下的线程安全。
public class SingletonLazyThreadSafe {
private static SingletonLazyThreadSafe instance;
private SingletonLazyThreadSafe() {}
public static synchronized SingletonLazyThreadSafe getInstance() {
if (instance == null) {
instance = new SingletonLazyThreadSafe();
}
return instance;
}
}
4. 双重检查锁定
双重检查锁定是一种在多线程环境下实现懒汉式单例的高效方式,也是线程安全的。它首先检查实例是否已经被创建,如果没有,则进入同步块创建实例。
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;
}
}
5. 静态内部类
这种方法利用了Java的类加载机制来实现线程安全的单例模式。静态内部类只有在第一次被使用时才会加载和初始化。
public class SingletonStaticInnerClass {
private SingletonStaticInnerClass() {}
private static class SingletonHolder {
private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();
}
public static SingletonStaticInnerClass getInstance() {
return SingletonHolder.INSTANCE;
}
}
6. 枚举
使用枚举(enum)实现单例是最简洁也是最推荐的方式,因为Java语言规范保证枚举的实例是单例的,并且是线程安全的。
public enum SingletonEnum {
INSTANCE;
public void someMethod() {
// 一些方法
}
}
总结
**** | 是否是线程安全的 |
---|---|
饿汉式 | 是 |
懒汉式(非同步方法) | 否 |
懒汉式(同步方法) | 是 |
双重检查锁定 | 是 |
静态内部类 | 是 |
枚举 | 是 |
在实际应用中,选择哪种单例实现方式取决于具体的需求和上下文环境。例如,如果实例化成本较高,可以考虑使用饿汉式;如果需要延迟实例化,可以考虑懒汉式或静态内部类方式。在多线程环境中,需要特别注意线程安全问题。