单例模式(Singleton Pattern)是一种创建型设计模式,它保证一个类仅有一个实例,并提供一个全局访问点来访问这个唯一实例。这种设计模式在多种场景中都非常有用,比如日志记录、配置管理、数据库连接池等。
在Java中实现单例模式有多种方式,以下是其中的几种常见方式:
- 饿汉式(线程安全)
饿汉式在类加载的时候就完成了初始化,所以类加载较慢,但获取对象的速度快。因为它是线程安全的,所以不需要额外的同步。
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }
- 懒汉式(线程不安全)
懒汉式在第一次调用getInstance()
方法时才会进行初始化,类加载较快,但第一次获取对象的速度较慢。由于它在方法内部才进行实例的创建,所以存在线程安全问题。
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
为了解决线程安全问题,我们可以使用synchronized
关键字进行同步,但这样会影响性能。
3. 双重检查锁定(Double-Checked Locking)
双重检查锁定是懒汉式的一种改进方式,它既能保证线程安全,又能减少不必要的同步开销。
public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
在这里,volatile
关键字确保了instance
变量的可见性,防止了指令重排。
4. 静态内部类
静态内部类的方式也是线程安全的,它利用了classloader的机制来保证初始化instance时只有一个线程。
public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } }
- 枚举(推荐)
使用枚举来实现单例模式是最简单且线程安全的方式。
public enum Singleton { INSTANCE; public void someMethod() { // do something... } }
使用枚举的方式不仅避免了多线程同步问题,而且还能防止反序列化重新创建新的对象。因此,在Java中实现单例模式时,枚举方式通常是一个很好的选择。