我試圖在Java中爲日期和數字實現格式化程序。但是一些java中的格式化程序不是線程安全的,例如。 (首先,我不明白他們爲什麼不是像DateTimeFormat
那樣的線程安全!)所以,在搜索了一下之後,我發現了ThreadLocal
變量。如果我在工廠類中實現ThreadLocal會發生什麼
我見過的所有片段都是ThreadLocal
,他們使用final
。當然,有一個格式化程序實例是有意義的。但是,可以說我們需要一個格式化程序,但是需要3個模式。
FormatFactory.java
public class FormatFactory {
public static ThreadLocal<DecimalFormat> getMoneyFormatter(final String pattern) {
return new ThreadLocal<DecimalFormat>() {
@Override
public DecimalFormat initialValue() {
DecimalFormat decFormat = new DecimalFormat(pattern);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
if (!pattern.equals(FormatPatterns.MT940_DECIMAL)) {
symbols.setGroupingSeparator('.');
}
decFormat.setMinimumFractionDigits(2);
decFormat.setDecimalFormatSymbols(symbols);
return decFormat;
}
};
}
}
Format.java
public static String money(BigDecimal amount, String pattern) {
return FormatFactory.getMoneyFormatter(pattern).get().format(amount);
}
使用
Format.money(balance, FormatPatterns.MT940_DECIMAL)
Format.money(balance, FormatPatterns.SIGNED_MONEY)
Format.money(balance, FormatPatterns.MONEY)
這還算是線程安全的我這個用法?
UPDATE:
答案here已經解決了我的問題。
我的片段是如下:
private static final ConcurrentMap<String, ThreadLocal<DecimalFormat>> decimialFormatsByPattern = new ConcurrentHashMap<String, ThreadLocal<DecimalFormat>>();
public static DecimalFormat getMoneyFormatter(final String pattern) {
ThreadLocal<DecimalFormat> decimalFormatter = decimialFormatsByPattern.get(pattern);
if (decimalFormatter == null) {
decimalFormatter = new ThreadLocal<DecimalFormat>() {
@Override
public DecimalFormat initialValue() {
DecimalFormat decFormat = new DecimalFormat(pattern);
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(',');
if (!pattern.equals(FormatPatterns.MT940_DECIMAL)) {
symbols.setGroupingSeparator('.');
}
decFormat.setMinimumFractionDigits(2);
decFormat.setDecimalFormatSymbols(symbols);
return decFormat;
}
};
decimialFormatsByPattern.putIfAbsent(pattern, decimalFormatter);
}
return decimalFormatter.get();
}
使用
public static String money(BigDecimal amount, String pattern) {
return FormatFactory.getMoneyFormatter(pattern).format(amount);
}
卡亞曼說:「......資源泄漏」。如果某個線程t創建一個DecimalFormat實例(或任何其他對象)並將其放在一個ThreadLocal對象中,那麼即使在線程t死後,ThreadLocal對象也將繼續保存該引用。線程t創建的對象永遠不會被垃圾收集。當你擁有一組固定的線程時,ThreadLocal很好用,但它可能會導致在不斷創建新的短暫線程的應用程序中出現問題。 (注意:當請求隊列中的積壓更改時,某些ExecutorService實現會創建並銷燬線程。) – 2015-01-21 17:55:12