Java单例模式 饿汉式详解
【创作】 不易,【点赞】 是情义,【关注】 是动力,【收藏】 是回忆。
示例代码地址:https://gitee.com/code-in-java/csdn-blog.git
一、概念与原理
Java中的单例模式是一种确保一个类只有一个实例,并提供一个全局访问点的设计模式。饿汉式单例模式是单例模式的一种实现方式,其特点是在类加载时就完成了实例的初始化,因此无需担心多线程同步问题。
二、实现方式
饿汉式单例模式主要通过将类的实例初始化放在静态变量中来实现,由于静态变量在类加载时就会初始化,因此这种方式可以保证实例的唯一性。常见的实现方式有两种:
1. 静态成员变量方式
1)在这种方式中,直接在类中声明一个私有的静态成员变量,并在声明时直接实例化。同时,提供一个公共的静态方法来返回这个实例。构造方法需要被私有化,以防止外部通过 new 关键字创建实例。
public class EagerSingleton1 {// 1. 私有静态成员变量,类加载时初始化 private static final EagerSingleton1 INSTANCE = new EagerSingleton1(); // 2. 私有构造方法,防止外部通过new创建实例 private EagerSingleton1() {} // 3. 公共静态方法,返回唯一实例 public static EagerSingleton1 getInstance() { return INSTANCE; }
}
2)调用示例:
EagerSingleton1 instance = EagerSingleton1.getInstance();
2. 静态代码块方式
1)虽然静态成员变量方式更为常见,但也可以使用静态代码块来实现相同的效果。在静态代码块中对静态成员变量进行初始化。这种方式在写法上略有不同,但本质上都是在 类加载时完成实例的初始化。
public class EagerSingleton2 { // 1. 私有静态成员变量 private static EagerSingleton2 INSTANCE; static { // 2. 静态代码块中初始化实例 INSTANCE = new EagerSingleton2(); } // 3. 私有构造方法 private EagerSingleton2() {} // 4. 公共静态方法 public static EagerSingleton2 getInstance() { return INSTANCE; } }
2)调用示例:
EagerSingleton2 instance = EagerSingleton2.getInstance();
三、优缺点分析
1. 优点
- 实现简单:代码简洁,易于理解。
- 线程安全:由于实例在类加载时就已创建,因此不存在多线程环境下的竞争问题。
2. 缺点
- 提前初始化:如果实例在程序运行过程中从未被使用,那么提前初始化会浪费内存资源。特别是对于资源占用较大的对象,这种浪费尤为明显。
四、应用场景
饿汉式单例模式适用于那些在程序启动时就需要加载且在整个应用程序生命周期中持续使用的资源。例如,配置文件的读取器、日志记录器等。这些资源通常不会频繁创建和销毁,且需要全局唯一访问点。
五、注意事项
在使用饿汉式单例模式时,需要注意以下几点:
1. 构造函数私有化:确保外部无法通过new关键字创建实例。
2. 静态成员变量或静态代码块:选择其中一种方式来实现实例的初始化。
3. 考虑资源占用:对于资源占用较大的对象,需要权衡提前初始化的利弊。
4. 序列化和反序列化问题:如果需要将单例对象序列化到文件或网络中,需要注意实现Serializable接口,并在类中提供readResolve方法来防止创建新的实例。但饿汉式单例由于实例在类加载时就已创建,通常不会通过序列化和反序列化的方式被创建新的实例。
结束语
Java单例模式的饿汉式是在类加载时就完成了实例的初始化,确保类只有一个实例,并提供全局访问点。这种方式实现简单,线程安全,无需担心多线程环境下的同步问题。然而,它的一个潜在缺点是可能导致资源在程序启动时就被提前占用,对于资源占用较大的对象来说,这可能会造成不必要的浪费。因此需要根据实际应用场景来分析使用。
【创作】 不易,【点赞】 是情义,【关注】 是动力,【收藏】 是回忆