历史上,懒惰初始化是为了优化资源使用而出现的,只有在对象真正需要时才创建它。最初,这在处理重对象、连接、缓存或实现复杂模式(例如,单例模式)时尤为重要。
问题是,如果一次性创建所有资源,即使对象不需要,也可能浪费内存、时间和计算能力。懒惰初始化解决了“延迟”创建的问题。
该解决方案通常通过检查来实现:如果对象尚未创建,则创建它,否则返回现有对象。
代码示例:
public class LazyHolder { private Resource resource; public Resource getResource() { if (resource == null) { resource = new Resource(); } return resource; } }
在多线程环境中,需要进行同步。
关键特性:
双重检查锁定(Double-Checked Locking)是否是懒惰初始化单例模式的可靠实现?
仅从Java 5开始,因为在此之前内存模型并未保证。必须为资源字段使用volatile关键字。
private volatile Resource resource; public Resource getResource() { if (resource == null) { synchronized(this) { if (resource == null) { resource = new Resource(); } } } return resource; }
对轻量级对象进行懒惰初始化有意义吗?
通常没有。最好立即创建“轻量级”对象,以保持代码的可读性并避免不必要的复杂性。
懒惰初始化在对象序列化时是否有效?
并不总是有效。在序列化时,可能会恢复为“旧”状态,或者需要在readObject()中增加额外的逻辑。
在高负载服务中,特殊对象池是懒惰解析的,但没有进行同步。两个线程同时初始化对象,导致内存泄漏和不可预测的错误。
优点:
缺点:
在大型Web应用中,分析仅通过API调用连接,使用懒惰初始化的代理对象和双重检查锁定。
优点:
缺点: