你真的懂Java延迟初始化吗?

引言

有时候,我们需要推迟一些高开销的对象初始化操作,并且只有当使用这些对象时才进行初始化。这让我立马反应到DCL的写法,但很快就被打脸,《Java并发编程实战》中表示不太推荐使用DCL。本文记录安全初始化的几个方式。

PS:fucking-java-concurrency代码解读上次学习了并发知识后,给仓库提交了一个final案例,没想到大佬很快就merge了,还给了我contributor,很开心,欢迎学习和Star!

请添加图片描述

附上仓库链接:https://github.com/WeiXiao-Hyy/blog

线程安全的延迟初始化

public class SafeLazyInitialization {
   
    private static Resource resource;
    
    public synchronized static Resource getInstance() {
   
        if (resource == null) {
   
            resource = new Resource();
        }
        return resource;
    }
}

getInstance的代码路径很短,因此如果getInstance没有被多个线程频繁调用,那么SafeLazyInitialization上不会存在激烈的竞争,从而能提供令人满意的性能。

静态初始化的对象都不需要显式的同步

静态代码块和静态变量初始化

静态代码块和静态变量初始化在类加载后并且被线程使用之前。并且JVM将在初始化期间获得一个锁,这个锁用于确保类的初始化在多线程环境下是安全的。每个线程至少获取一次锁,可能有多个线程同时尝试使用同一个类,而JVM需要确保类的初始化只被执行一次,在初始化完成之前,其他线程需要等待。

因此无论是在被构造期间还是被引用,静态初始化的对象都不需要显式的同步。

提前初始化

通过使用提前初始化,避免了在每次调用SafeLazyInitialization中的getInstance时所产生的同步开销。

public class EagerInitialzation {
   
    private static Resource resource = new Resource();
    
    public static Resource getResource() {
   
        return resource;
    }
}

延长初始化占位类模式

首先明确静态内部类的加载过程

静态内部类的加载不需要依附外部类,在使用时才会加载。同时在加载静态内部类的过程中也会加载外部类。

通过以上理论可以形成一种延迟初始化技术,从而在常见的代码路径并不需要同步。

public 
  • 21
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WeiXiao_Hyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值