在大多數應用中,差別都不會有問題,所以你要更簡單的選擇。
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秒。除非你的應用格式字符串百萬每秒,這是不值得考慮:-)
除非你能證明第二個導致真正的性能問題,這是非常不可能的,保持簡單,創建一個新的,當你需要它。 –
創建新的實例。如果你證明對你的用例來說很慢,那麼考慮使用ThreadLocal。 ThreadLocal的複雜性在於,當線程被銷燬時,必須確保清除ThreadLocal,否則可能導致內存泄漏。 – Augusto
@August如果線程被破壞,清理不成問題,這是一個問題,當它是池中的一個線程時,可用於其他任務。關聯的ThreadLocal內容不能被垃圾收集,但它也不再使用。 – bowmore