Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing the lazily initialized field. Depending on what fraction of lazily initialized fields eventually require initialization, how expensive it is to initialize them, and how often each field is accessed, lazy initialization can (like many "optimizations") actually harm performance.

The only way to know for sure is to measure the performance of the class with and without lazy initialization.

Principle

  • Normal initialization of an instance field - Under most circumstances, normal initialization is preferable to lazy initialization.

    // Normal initialization of an instance field

    private final FieldType field = computeFieldValue();

  • synchronized accessor - If you use lazy initialization to break an initialization circularity, use a synchronized accessor, as it is the simplest, clearest alternative:

    // Lazy initialization of instance field - synchronized accessor

    private FieldType field;

    synchronized FieldType getField() {

    if (field == null)

    field = computeFieldValue();

    return field;

    }

    Both of these idioms (normal initialization and lazy initialization with a synchronized accessor ) are unchanged when applied to static fields, except that you add the static modifier to the field and accessor declarations.

  • lazy initialization holder class idiom - If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom .

    // Lazy initialization holder class idiom for static fields

    private static class FieldHolder {

    static final FieldType field = computeFieldValue();

    }

    static FieldType getField() { return FieldHolder.field; }

  • Double-check idiom - If you need to use lazy initialization for performance on an instance field, use the double-check idiom.

    // Double-check idiom for lazy initialization of instance fields

    private volatile FieldType field;

    FieldType getField() {

    FieldType result = field;

    if (result == null) { // First check (no locking)

    synchronized(this) {

    result = field;

    if (result == null) // Second check (with locking)

    field = result = computeFieldValue();

    }

    }

    return result;

    }

  • Single-check idiom - Occasionally, you may need to lazily initialize an instance field that can tolerate repeated initialization.

    // Single-check idiom - can cause repeated initialization!

    private volatile FieldType field;

    private FieldType getField() {

    FieldType result = field;

    if (result == null)

    field = result = computeFieldValue();

    return result;

    }

    Note

    When the double- check or single-check idiom is applied to a numerical primitive field, the field's value is checked against 0 (the default value for numerical primitive variables) rather than null.

  • Racy single-check idiom - If you don't care whether every thread recalculates the value of a field, and the type of the field is a primitive other than long or double , then you may choose to remove the volatile modifier from the field declaration in the single-check idiom(e.g. String instances to cache their hash codes).

    // racy single-check idiom - can cause repeated initialization!

    private FieldType field;

    private FieldType getField() {

    FieldType result = field;

    if (result == null)

    field = result = computeFieldValue();

    return result;

    }

    Summary

    You should initialize most fields normally, not lazily. If you must initialize a field lazily in order to achieve your performance goals, or to break a harmful initialization circularity, then use the appropriate lazy initialization technique. For instance fields, it is the double-check idiom; for static fields, the lazy initialization holder class idiom. For instance fields that can tolerate repeated initialization, you may also consider the single-check idiom.

Effective Java 71 Use lazy initialization judiciously的更多相关文章

  1. Effective Java 54 Use native methods judiciously

    Java Native Interface(JNI) allows Java applications to call native methods, which are special method ...

  2. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  3. 《Effective Java》读书笔记 - 10.并发

    Chapter 10 Concurrency Item 66: Synchronize access to shared mutable data synchronized这个关键字不仅保证了同步,还 ...

  4. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  5. 【Effective Java】阅读

    Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...

  6. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  7. Effective java笔记(九),并发

    66.同步访问共享的可变数据 JVM对不大于32位的基本类型的操作都是原子操作,所以读取一个非long或double类型的变量,可以保证返回的值是某个线程保存在该变量中的,但它并不能保证一个线程写入的 ...

  8. 单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)

    首先这两种方式都是延迟初始化机制,就是当要用到的时候再去初始化. 但是Effective Java书中说过:除非绝对必要,否则就不要这么做. 1. DCL (double checked lockin ...

  9. Effective Java 阅读笔记——并发

    66:同步访问共享的可变数据 synchronized:1互斥,阻止线程看到的对象处于不一致的状态:2保证线程在进入同步区时能看到变量的被各个线程的所有修改 Java中,除了long或者double, ...

随机推荐

  1. tips instanceof运算符和typeof运算符的区别

    tips instanceof运算符和typeof运算符的区别  一.instanceof运算符:       此运算符可以判断一个变量是否是某个对象(类)的实例,返回值是布尔类型的(true和fal ...

  2. vertical-align两种应用场合

    vertical-align两种应用场合 (1)用在td/th中或display:table-cell元素中:让当前元素中的文本内容在竖直方向上居中    css部分:    .content{   ...

  3. 流行的ios开源项目

    本文介绍一些流行的iOS的开源项目库 1.AFNetworking 更新频率高的轻量级的第三方网络库,基于NSURL和NSOperation,支持iOS和OSX.https://github.com/ ...

  4. SpringMVC基础——一个简单的例子

    一.导入 jar 包 二.配置 web.xml 文件 <servlet> <servlet-name>dispatcherServlet</servlet-name> ...

  5. 发现自己喜欢了移动端开发--Android

    喜欢.net一直到现在了,但是自己做过的项目都不是让我自己很满意,不知道为什么,可能是自己的要求比较高吧! 下面自己记录自己的学习 src专门存放我们java源代码的包 Android 4.2.2存放 ...

  6. WCF使用泛型方法的问题

    public IList getModelList(string type, string SQL, List<string> list){ try { IList Mlist = new ...

  7. Win7配置Go环境

    最近想学习下Go语言,先从最基本的Hello Go开始,搭建Go开发环境 一.下载Go包 由于Go官网国内访问经常有问题,可以从国内的镜像下载: http://www.golangtc.com/ 二. ...

  8. unity3d拓展编辑器Editor的使用

    Editor可以拓展Inspector窗口 可以通过代码自己绘制监测面板 先来看一个效果:

  9. 线段树或树状数组---Flowers

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=4325 Description As is known to all, the blooming tim ...

  10. Android应用与系统安全防御

    来源:HTTP://WWW.CNBLOGS.COM/GOODHACKER/P/3864680.HTML ANDROID应用安全防御 Android应用的安全隐患包括三个方面:代码安全.数据安全和组件安 ...