gpt4 book ai didi

java - Effective Java - 尽管创建了多个实例,但相同的方法调用时间

转载 作者:行者123 更新时间:2023-11-30 06:26:09 26 4
gpt4 key购买 nike

我正在学习 Effective Java,在本书的第 5 条中,Joshua Bloch 谈到了避免创建不必要的对象。一个示例演示了一旦计算出其值就永远不会修改的可变 Date 对象。

这里是“坏习惯”:

public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}

// DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0
&& birthDate.compareTo(boomEnd) < 0;
}

每次调用 isBabyBoomer 方法时都不必要地创建一个新的 Calendar、TimeZone 和两个 Date 实例 - 这对我来说显然很有意义。

这里是改进后的代码:

public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}

/**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END;

static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}

public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&& birthDate.compareTo(BOOM_END) < 0;
}

Calendar、TimeZone 和 Date 实例仅在初始化时创建一次。Bloch 解释说,如果频繁调用方法 isBabyBoomer(),这会显着提高性能。

在他的机器上:
错误版本:1000 万次调用需要 32,000 毫秒
改进版本:130 毫秒调用 1000 万次

但是当我在我的系统上运行示例时,性能完全相同(14 毫秒)。实例只创建一次的编译器特性吗?

编辑:
这是我的基准:

    public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(1960, Calendar.JANUARY, 1, 1, 1, 0);
Person p = new Person(cal.getTime());
long startTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
p.isBabyBoomer();
}
long stopTime = System.nanoTime();
long elapsedTime = stopTime - startTime;
double mseconds = (double) elapsedTime / 1000000.0;
System.out.println(mseconds);
}

干杯,马库斯

最佳答案

您的基准是错误的。使用最新的 Java 7 和适当的预热,我发现这两种方法之间存在显着差异:

Person::main: estimatedSeconds 1 = '8,42'
Person::main: estimatedSeconds 2 = '0,01'

这里是完整的可运行代码:

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class Person {
private Date birthDate;
static Date BOOM_START;
static Date BOOM_END;

public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}

static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}

public boolean isBabyBoomerWrong() {
// Unnecessary allocation of expensive object
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0
&& birthDate.compareTo(boomEnd) < 0;
}

public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&& birthDate.compareTo(BOOM_END) < 0;
}

public static void main(String[] args) {
Person p = new Person(new Date());

for (int i = 0; i < 10_000_000; i++) {
p.isBabyBoomerWrong();
p.isBabyBoomer();
}

long startTime = System.nanoTime();

for (int i = 0; i < 10_000_000; i++) {
p.isBabyBoomerWrong();
}

double estimatedSeconds = (System.nanoTime() - startTime) / 1000000000.0;
System.out.println(String.format("Person::main: estimatedSeconds 1 = '%.2f'", estimatedSeconds));

startTime = System.nanoTime();

for (int i = 0; i < 10_000_000; i++) {
p.isBabyBoomer();
}

estimatedSeconds = (System.nanoTime() - startTime) / 1000000000.0;
System.out.println(String.format("Person::main: estimatedSeconds 2 = '%.2f'", estimatedSeconds));

}
}

关于java - Effective Java - 尽管创建了多个实例,但相同的方法调用时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14791836/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com