我有一个使用DecimalFormat
(https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html)API的实现。
Solution1 :参数是因为DecimalFormat
不是线程安全的,我倾向于将ThreadLocal
用于DecimalFormat
创建使其线程安全。此外,它将为每次调用保存DecimalFormat对象的创建
private static final ThreadLocal<DecimalFormat> restrictTo1DecimalPlace =
ThreadLocal.withInitial
(() -> new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));
解决方案2 :另一个简单的解决方案是放弃对象可重用性并每次创建DecimalFormat
对象。
new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(decimalValueToFormat)
什么更好?
答案 0 :(得分:1)
在大多数应用程序中,差异无关紧要,因此您需要更简单的选项。
您可以通过对两种选择进行基准测试来验证这一点:
public abstract class Benchmark {
public static void main(String[] args) throws Exception {
final ThreadLocal<DecimalFormat> restrictTo1DecimalPlace =
ThreadLocal.withInitial
(() -> new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));
Benchmark[] marks = {
new Benchmark("ThreadLocal") {
@Override
protected Object run(int iterations) throws Throwable {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append(restrictTo1DecimalPlace.get().format(i * 0.01));
}
return sb;
};
},
new Benchmark("new Format") {
@Override
protected Object run(int iterations) throws Throwable {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append(new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(i * 0.01));
}
return sb;
};
},
};
for (Benchmark mark : marks) {
System.out.println(mark);
}
}
final String name;
public Benchmark(String name) {
this.name = name;
}
@Override
public String toString() {
return name + "\t" + time() + " ns / iteration";
}
private BigDecimal time() {
try {
// automatically detect a reasonable iteration count (and trigger just in time compilation of the code under test)
int iterations;
long duration = 0;
for (iterations = 1; iterations < 1_000_000_000 && duration < 1_000_000_000; iterations *= 2) {
long start = System.nanoTime();
run(iterations);
duration = System.nanoTime() - start;
}
return new BigDecimal((duration) * 1000 / iterations).movePointLeft(3);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
/**
* Executes the code under test.
* @param iterations
* number of iterations to perform
* @return any value that requires the entire code to be executed (to
* prevent dead code elimination by the just in time compiler)
* @throws Throwable
* if the test could not complete successfully
*/
protected abstract Object run(int iterations) throws Throwable;
}
在我的机器上打印:
ThreadLocal 260.132 ns / iteration
new Format 363.199 ns / iteration
因此从ThreadLocal获取格式或创建新格式之间的区别大约为0.0000001秒。除非您的应用程序每秒格式化数百万个字符串,否则不值得考虑: - )
答案 1 :(得分:0)
我想知道是否存在显着差异
最近,JVM的性能已成倍增加,因此对象创建不再像以前那样昂贵。
但新的DecimalFormat的分配对内存的影响可能也会消耗时间。 创建新实例非常合理,这就是Java代码的工作原理。
您可以尝试的一件事是预先分配DecimalFormat实例并将它们保存在简单的object pool中。