互联网科技Java程序员

静态初始化中不能放入繁重计算,否则会变慢!

2019-04-10  本文已影响3人  Java高级架构狮

在类初始化期间计算不可变数据结果,并将结果保存在static final字段中是一种非常常见的做法。实际上,这正是静态初始化器的设计目标。

以下是在初始化时构建一些静态表的典型示例:

public class StaticExample {
    static final long[] TABLE = new long[100_000_000];

    static {
        TABLE[0] = 0;
        for (int i = 1; i < TABLE.length; i++) {
            TABLE[i] = nextValue(TABLE[i - 1]);
        }
    }

    private static long nextValue(long seed) {
        return seed * 0x123456789L + 11;
    }

    ...
}

在我的JDK 11.0.1笔记本电脑上,静态初始化程序在大约540毫秒内填充100M元素的数组。

现在让我们简单地删除static并填充构造函数中的数组。

public class NonStaticExample {
    final long[] TABLE = new long[100_000_000];

    {
        TABLE[0] = 0;
        for (int i = 1; i < TABLE.length; i++) {
            TABLE[i] = nextValue(TABLE[i - 1]);
        }
    }

    private static long nextValue(long seed) {
        return seed * 0x123456789L + 11;
    }

    public static void main(String[] args) {
        new NonStaticExample();
    }
}

构造函数在138毫秒内填充类似的数组。几乎快4倍!

为什么静态初始化器会变慢?这必须与JIT编译有关。

解决方法非常简单:

只是不要直接在未初始化的类中进行繁重的计算。如果将计算逻辑放在没有静态初始化程序的辅助类中,它将不会受到性能损失的影响。

public class StaticExample {
    static final long[] TABLE = Helper.prepareTable();

    private static class Helper {

        static long[] prepareTable() {
            long[] table = new long[100_000_000];
            for (int i = 1; i < table.length; i++) {
                table[i] = nextValue(table[i - 1]);
            }
            return table;
        }

        static long nextValue(long seed) {
            return seed * 0x123456789L + 11;
        }
    }
}

读者福利:

分享免费学习资料

针对于还会准备免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能点个小赞和关注下我,以后还会更新技术干货,谢谢您的支持!

资料领取方式:加入Java技术交流群963944895,私信管理员即可免费领取

上一篇下一篇

猜你喜欢

热点阅读