I woke up this morning thinking I
knew all there was to know about lazy loading singletons in Java. Boy,
was I wrong. Java doesn't cease to surprise me, even after all these
years.
First, why would you want to lazy load a singleton? In production,
you typically want to eagerly load all your singletons so you catch
errors early and take any performance hit up front, but in tests and
during development, you only want to load what you absolutely need so as
not to waste time.
Before Java 1.5, I lazy loaded singletons using plain old synchronization, simple but effective:
static Singleton instance;
public static synchronized
Singleton getInstance() {
if (instance == null)
instance == new Singleton();
return instance;
}
Changes to the memory model in 1.5 enabled the infamous Double-Checked
Locking (DCL) idiom. To implement DCL, you check a volatile field in the
common path and only synchronize when necessary:
static volatile
Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance == new Singleton();
}
}
return instance;
}
But volatile
isn't that much faster than synchronized
, synchronized
is pretty fast nowadays, and DCL requires more code, so even after 1.5 came out, I continued using plain old synchronization.
Imagine my surprise today when Jeremy Manson pointed me to the Initialization on Demand Holder (IODH) idiom
which requires very little code and has zero synchronization overhead. Zero
, as in even faster than volatile
. IODH requires the same number of lines of code as plain old synchronization, and it's faster than DCL!
IODH utilizes lazy class initialization. The JVM won't execute a
class's static initializer until you actually touch something in the
class. This applies to static nested classes, too. In the following
example, the JLS guarantees
the JVM will not initialize instance
until someone calls getInstance()
:
static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
Why didn't IODH register in my brain sooner? I'm on the JMM mailing list
after all. I think I had a mental block due to the fact that exceptions
thrown in class initializers used to be difficult to debug, i.e. before
nested exceptions. If I recall correctly, you would get an ExceptionInInitializerError
(which would tromp the root exception) followed by a series of ClassNotFoundException
s. Lazy loading from an application thread didn't suffer this problem.
Today, exceptions in static initializers are easy enough to diagnose--they appear nested in the ExceptionInInitializerError
, so use IODH from now qualm free.
Update:
Credit where credit is due, Effective Java
(copyright 2001) detailed this pattern under item 48. It goes on to
point out that you still have to use synchronization or DCL in
non-static contexts.
I also switched singleton handling in my framework from
synchronization to DCL and saw another 10% performance boost (compared
to before I started using cglib's fast reflection). I only used one
thread in my micro-benchmark, so the boost to concurrency could be even
greater given that I replaced a heavily contended lock with a relatively
fine grained volatile field access.
分享到:
相关推荐
在网页开发中,"页面实现Lazy Loading效果"是一种优化用户体验的技术策略,特别是在处理大量图片或者内容的页面时。Lazy Loading,即延迟加载或惰性加载,是指只在用户滚动到可视区域时才加载图片或其他资源,而不是...
In this article I want to discuss the lazy loading mechanism provided by NHibernate. It is recommended for maximum flexibility to define all relations in your domain as lazy loadable. This is the ...
当应用需要加载图片时,特别是网络图片,采用“懒加载”(Lazy Loading)策略是提高性能和节省资源的有效方式。这个“IOS TableView Lazy Loading Demo”就是演示了如何将UITableView与懒加载技术相结合,以优化用户...
Lazy Loading:懒加载的常见问题与解决方案.docx
"lazyloading.rar"这个压缩包文件提供了一个实现移动端图片懒惰加载的解决方案。下面将详细解释这种技术的原理、优势、实现方式以及如何使用压缩包内的文件。 图片懒惰加载是一种优化策略,主要用于网页或应用中,...
Lazy Loading:CSS懒加载策略.docx
Lazy Loading:懒加载技术概论.docx
Lazy Loading:JavaScript懒加载实现.docx
Lazy Loading:懒加载与用户体验.docx
Lazy Loading:视频懒加载实现方法.docx
Lazy Loading:懒加载与SEO优化.docx
Lazy Loading:懒加载与性能优化.docx
0023_极智AI_解读算法部署中需要注意的LazyLoading-个人笔记
Lazy Loading:懒加载框架与库介绍.docx
Lazy Loading:懒加载的历史与发展.docx
Lazy Loading:懒加载未来趋势与研究.docx
在提供的"lazyLoading.rar"压缩包中,包含了一个完整的实现图片懒加载的实例。其中,HTML5页面应该包含了使用`data-src`的`<img>`标签,JavaScript文件(可能是.js后缀)则包含了处理滚动事件和图片加载逻辑的代码。...
Lazy Loading:懒加载在移动应用中的实践.docx
Blazor 懒加载(Lazy Loading)是一种优化Web应用程序性能的技术,主要应用于Blazor框架,它允许我们在需要时才加载特定的组件或模块,而不是一次性加载整个应用。这样可以显著减少初始页面加载时间,提高用户体验,...