Java单例模式是一种常见的设计模式,它可以确保一个类只有一个实例,并提供全局访问点。在Java中,单例模式通常用于管理全局资源,例如数据库连接池、日志记录器等。
1.饿汉式实现方法
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
// 私有构造函数
}
public static Singleton getInstance() {
return instance;
}
}
在这个实现方法中,Singleton类在类加载时就创建了一个静态实例,并在getInstance方法中返回该实例。由于静态实例是在类加载时创建的,因此它是线程安全的。
2.懒汉式实现方法
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数
}
public static synchronized Singleton getInstance()
{ if (instance == null)
{ instance = new Singleton(); } return instance; }
}
在这个实现方法中,Singleton类在第一次调用getInstance方法时才创建实例。由于在多线程环境下可能会出现竞态条件,因此需要在getInstance方法中加锁或使用双重检查锁定来确保线程安全。
DCL实现单例模式
public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
在上面的代码中,使用了volatile关键字来确保instance的可见性,同时也保证了instance的初始化顺序。
使用DCL可以在保证线程安全的同时,避免了每次获取实例都需要加锁的开销。不过需要注意的是,在早期版本的JDK中,DCL可能存在重排序问题,导致获取到未完全初始化的实例,所以需要在使用DCL时,注意JDK的版本和实现细节。
3.枚举实现单例模式
public enum Singleton {
INSTANCE;
public void doSomething() {
// 单例操作
}
}
使用枚举(Enum)实现单例模式是一种简洁、安全、且易于理解的方式,因为枚举类的实例化是线程安全的,而且在Java中,枚举是天然的单例模式。
4.内部类实现单例模式
public class Singleton {
//私有化构造函数,防止外部直接实例化
private Singleton() {}
//内部静态类,用于延迟加载单例对象
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
}
//提供公共静态方法,返回单例对象
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
在上述代码中,Singleton类的构造函数是私有的,这意味着只能在类的内部实例化对象。SingletonHolder是一个私有的静态内部类,它持有一个Singleton实例,并在内部静态变量中进行初始化。getInstance()方法返回SingletonHolder中的Singleton实例,从而保证了单例模式的正确性。由于静态内部类只会在需要时才会被加载,因此这种方式实现了延迟加载的效果,也避免了多线程下的同步问题。