延迟初始化(lazy initialization),也就是在真正被使用的时候才开始初始化的技巧。
不论是静态还是实例,都可以进行延迟初始化。
其本质是初始化开销和访问开销之间的权衡。
毕竟是一种优化技巧,使用不当会起反效果。
尤其是在多线程场景中这种反效果会尤为明显,因为我们要对这个进行延迟初始化的field进行同步。

先一步步开始,如果初始化开销不值一提,我们只需要保证其不可变即可:

private final FieldType field1 = computeFieldValue();

如果还有的商量,初始化开销可能让人在意,下面是最简单的的方式,直接在访问方法声明里加了synchoronized修饰,这种方式将访问开销最大化了:

private FieldType field2;

synchronized FieldType getField2() {
if (field2 == null)
field2 = computeFieldValue();
return field2;
} private static FieldType computeFieldValue() {
return new FieldType();
}

如果要改为静态的也不过是加上static修饰,但对于静态初始化,我们可以使用class holder方式:

private static class FieldHolder {
static final FieldType field = computeFieldValue();
} static FieldType getField3() {
return FieldHolder.field;
} private static FieldType computeFieldValue() {
return new FieldType();
}

这种方式感觉不错,我们没有进行额外的同步处理,只有在访问getField3的时候FieldHolder才会被初始化。
所以这种情况属于没有增加访问开销也保证了延迟特性。

这次试试优化一下实例field的访问开销,最经典的就是double-check了,这个东西经常出现在笔试题中:

private volatile FieldType field4;

FieldType getField4() {
FieldType result = field4;
if (result == null) {
synchronized (this) {
result = field4;
if (result == null)
field4 = result = computeFieldValue();
}
}
return result;
}
private static FieldType computeFieldValue() {
return new FieldType();
}

代码中使用了result局部变量,这样做虽然不是必要的,但这样可以确保field已被初始化的情况下被读取一次,可以提高少许效率。

以上就是延迟初始化的一些常用方式。
延迟初始化看起来不错,但建议权衡访问和创建的开销,对于实例field使用double-check,对于静态field使用holder class,以在多线程访问时保证check-then-action的原子性。

Java - 延迟初始化的更多相关文章

  1. Effective Java 第三版——83. 明智谨慎地使用延迟初始化

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  2. JAVA 双重检查锁定和延迟初始化

    双重检查锁定的由来在Java程序中,有时需要推迟一些高开销的对象的初始化操作,并且只有在真正使用到这个对象的时候,才进行初始化,此时,就需要延迟初始化技术.延迟初始化的正确实现是需要一些技巧的,否则容 ...

  3. Java对象延迟初始化的实现

    一.什么是延迟初始化? 在Java多线程程序中,有时候需要采用延迟初始化来降低初始化类和创建对象的开销. 延迟初始化实际上就是:当我们要进行一些高开销的对象初始化操作时,只有在使用这些对象时才进行初始 ...

  4. Effective Java 之-----关于延迟初始化

    1.大多数情况下,正常的初始化要优先于延迟初始化. private final FieldType field = computeFieldValue(); 2.如果利用延迟优化来破坏初始化的循环,就 ...

  5. 从学习“单例模式”学到的Java知识:双重检查锁和延迟初始化

    一切真是有缘,上午刚刚看完单例模式,还在为其中的代码块同步而兴奋,下午就遇见这篇文章:双重检查锁定与延迟初始化.我一看,文章开头语出惊人,说这是一种错误的优化,我说,难道上午学的东西下午就过时了吗?仔 ...

  6. 双重检查锁定与延迟初始化(转自infoq)

    很好的文章,转自http://www.infoq.com/cn/articles/double-checked-locking-with-delay-initialization 在java程序中,有 ...

  7. volatile双重检查锁定与延迟初始化

    一.基本概念: 1.volatile是轻量级的synchronized,在多核处理器开发中保证了共享变量的“可见性”.可见性的意思是,当一个线程修改一个共享变量时,另一个线程能读到这个修改的值. 2. ...

  8. spring3: 延迟初始化Bean

    3.3.1  延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy- ...

  9. (转)Android高性能编程(2)--延迟初始化

    上一篇文章,讲到了很多Android应用开发中需要注意的性能和内存方面的技巧.这一篇文章就是从smali指令级来分析性能优化和内存优化的问题. 如何解决界面启动时间开销大的问题 我们在编写Androi ...

随机推荐

  1. Ubuntu安装Apache+PHP

    1.Ubuntu 安装Apache 安装Apache sudo apt-get install apache2 修改端口号 打开 etc/apache2/port.config 修改 port 80 ...

  2. hdu 4325 Flowers(区间离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 Flowers Time Limit: 4000/2000 MS (Java/Others)    Mem ...

  3. 基于duilib的虚拟列表实现

    本文由作者邹启文授权网易云社区发布. 在邮箱大师选择duilib作为UI开发库后,我们面临这样一个问题.随着时间的积累,用户数据会越来越多,如何保证我们的软件在展示这些数据时依然保持非常好的体验? 原 ...

  4. JQuery Mobile - 为什么绑定事件后会被多次执行?

    JQuery Mobile 在绑定事件时候,发现会被多次执行,为什么啊? 原来,jquery click  不是替换原有的function ,而是接着添加,所以才会执行次数越来越多,怎么办才能按需实现 ...

  5. 2017 NAIPC A:Pieces of Parentheses

    my team solve the problem in the contest with similar ideathis is a more deep analysis The main idea ...

  6. docker-compose批量管理docker容器

    # docker-compose编排工具 #批量管理(构建.启动容器) #centos7环境准备#安装docker-ce #安装docker-compose v1. sudo curl -o /usr ...

  7. django项目 设置session 实现用户登入登出

    一.配置文件 settngs.py中 # 使用django认知系统的登录状态装饰器时,没有登录的话,跳往登录页面后路径是/acount/login 需要重新指定 LOGIN_URL = '/user/ ...

  8. 使用过Memcache缓存吗?如果使用过,能够简单描述下其工作原理吗?

    Memcache是把所有数据保存在内存中,采用hash表的方式,每条数据由key和value组成,每个key独一无二的.Memcache采用LRU算法逐渐把过期数据清除掉.

  9. SpringBoot程序远程debug

    所谓的远程调试就是服务端程序运行在一台远程服务器上,我们可以在本地服务端的代码(前提是本地的代码必须和远程服务器运行的代码一致)中设置断点,每当有请求到远程服务器时时能够在本地知道远程服务端的此时的内 ...

  10. jvm(1)类的加载(二)(自定义类加载器)

    [深入Java虚拟机]之四:类加载机制 1,从Java虚拟机的角度,只存在两种不同的类加载器: 1,启动类加载器:它使用C++实现(这里仅限于Hotspot,也就是JDK1.5之后默认的虚拟机,有其他 ...