基本概念
Singleton Patterns: (GoF Definition) Ensure a class only has one instance, and provide a global point of access to it.
实现代码
Lazy Initialization
A technique through which you delay the object creation process. It says that you should create an object only when it is required.
这种方法不是线程安全的,在多线程情况,可能创建多个单例类的对象。
Eager initialization
在任何线程访问这个类之前,
_captain
已经被创建并初始化。类加载在 Java 中是线程安全的,JVM 确保只有一个线程对
_captain
进行初始化操作。这种方式会导致资源浪费,因为无论是否需要相关实例,都会在类加载时进行初始化。
Use of “synchronized” keyword
synchronized
确保在同一时间只有一个线程可以进入被修饰的方法,从而避免了多线程并发访问时可能引发的问题。- JVM ensures this. Internally, it uses locks on a class or an object to ensure that only one thread is accessing the data.
每次调用同步方法都需要获取和释放锁,成为性能瓶颈。且不正确使用可能导致死锁。
Bill Pugh’s Solution
内部类
SingletonHelper
的静态成员 _captain
在类加载时就被初始化,不需要依赖外部类的实例。且 final
意味着这个属性的值一旦被赋值,就不能再被修改,保证只有一个实例被创建。Double-Checked Locking
在
if
条件内使用 synchronized
块,避免每次调用方法时都进行同步操作,减少性能开销。Q & A
When should I consider singleton patterns?
In general, you can consider singleton patterns to implement a centralized management system, to maintain a common log file, to maintain thread pools in a multithreaded environment, to implement caching mechanism or device drivers, and so forth.
具体应用
Spring 框架中的 Bean 默认情况下是单例的,Spring 容器(BeanFactor →
ApplicationContext
)负责创建和管理它们,从而有助于提高应用程序的性能,降低资源消耗。例如,
@Service
注解相当于在 Spring 中声明一个特殊的 Bean,用于提供业务逻辑,然后使用 @Autowired
实现依赖注入。如果不通过 Bean 进行依赖注入,开发者通常需要手动
new
一个类的对象实例,从而增加了管理成本(管理对象的生命周期,包括创建、初始化、销毁等),可能导致资源泄漏或不正确的对象状态。