单例模式是一种常用的软件设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。饿汉式和懒汉式是单例模式的两种实现方式,它们的主要区别在于实例的创建时机。
饿汉式单例模式
特点:
- 在类加载时就初始化实例,因此也被称为“急切式”或“饿汉式”。
- 线程安全,因为实例在类加载时就已经创建,不会出现多线程并发创建实例的问题。
- 缺点是实例的创建不依赖于实际需求,可能会占用不必要的资源。
实现代码(Java 示例):
|
|
懒汉式单例模式
特点:
- 实例的创建是“懒惰”的,即只有在第一次调用
getInstance()方法时才会创建实例。 - 需要处理线程安全问题,否则在多线程环境下可能会创建多个实例。
实现方式:
-
非线程安全的懒汉式:
1 2 3 4 5 6 7 8 9 10 11 12public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }这种实现方式在多线程环境下是不安全的,可能会导致多个实例被创建。
-
线程安全的懒汉式(加锁):
1 2 3 4 5 6 7 8 9 10 11 12public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }这种方式虽然线程安全,但每次调用
getInstance()方法时都会加锁,效率较低。 -
双重校验锁(DCL):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16public 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; } }这种方式既保证了线程安全,又避免了每次调用都加锁,效率较高。
总结
- 饿汉式:线程安全,但实例在类加载时就创建,可能会浪费资源。
- 懒汉式:实例按需创建,但需要处理线程安全问题。其中,双重校验锁(DCL)是懒汉式的最佳实现方式。
在实际开发中,选择哪种单例模式取决于具体需求。如果实例创建成本不高且类加载时就可初始化,可以选择饿汉式;如果需要按需创建实例且线程安全很重要,则推荐使用双重校验锁实现的懒汉式。