我正在尝试在 Java 中实现日期和数字的格式化程序。但是java中的一些格式化程序不是线程安全的,例如。 DecimalFormat, SimpleDateFormat
!(首先,我不明白为什么它们不像DateTimeFormat
那样线程安全!)所以,经过一番搜索后,我发现了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)
在这种用法中它仍然是线程安全的吗???
更新:
答案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);
}
最佳答案
现在,每次调用 getMoneyFormatter
时,您都会返回一个新的 ThreadLocal
。您应该只初始化一次。
但是,使用 ThreadLocal 可能会导致资源泄漏,因此除非您确实知道需要它,否则在需要时创建一个新的格式化程序会更简单。
关于java - 如果我在工厂类中实现 ThreadLocal 会发生什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28061684/