单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。这对于需要控制资源访问、限制实例数量或跟踪对象状态的情况很有用。
在Java中,有几种实现单例模式的方式,其中比较常见的有以下几种:
懒汉模式就是使用的时候创建对象,饿汉模式就是提前加载创建好的静态static对象,双重检查模式就是两次检查避免多线程造成创建了多个对象。
在第一次访问时创建实例,如果实例已经存在,则直接返回。线程不安全,如果没有线程安全的处理方式,可能会导致多个线程同时创建实例的问题。(非线程安全)
public class LazySingleton {
// 私有静态变量,用于保存唯一实例
private static LazySingleton instance;
// 私有构造方法,防止外部直接实例化
private LazySingleton() {}
// 公共静态方法,提供全局访问点
public static synchronized LazySingleton getInstance() {
// 如果实例尚未创建,则在同步块内创建实例
if (instance == null) {
instance = new LazySingleton();
}
// 返回实例
return instance;
}
}
在类加载时就创建实例,确保了线程安全,但可能导致资源浪费,因为实例在应用程序启动时就被创建,即使后续不使用。(线程安全)
public class EagerSingleton {
// 在类加载时就创建实例
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造方法,防止外部直接实例化
private EagerSingleton() {}
// 提供全局访问点
public static EagerSingleton getInstance() {
return instance;
}
}
在懒汉式的基础上,加入了双重检查,减少了加锁的频率,提高了性能。需要使用volatile关键字来确保可见性(线程安全)
public class DoubleCheckedSingleton {
// volatile关键字确保当instance变量被修改时,所有线程都能够立即看到修改。
private static volatile DoubleCheckedSingleton instance;
// 私有构造方法,防止外部直接实例化
private DoubleCheckedSingleton() {}
// 提供一个全局访问点,使用双重检查来确保在多线程环境下只创建一个实例
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
这只是单例模式的一些实现方式,每种方式都有其优缺点,选择适合项目需求的方式很重要。此外,在Java中,如果使用静态内部类、枚举等方式也能实现单例模式。
下面是一个简单的 Java 单例模式的例子,采用懒汉式实现,使用了双重检查锁定来确保线程安全和性能:
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;
}
// 其他业务逻辑方法
public void doSomething() {
System.out.println("Singleton is doing something.");
}
public static void main(String[] args) {
// 获取单例实例
Singleton singleton1 = Singleton.getInstance();
// 调用业务逻辑方法
singleton1.doSomething();
// 尝试创建第二个实例,但由于是单例模式,将得到相同的实例
Singleton singleton2 = Singleton.getInstance();
// 输出 true,表示两个引用指向同一个对象
System.out.println(singleton1 == singleton2);
}
}
在上述代码中:
单例模式适用于以下情况:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。