java - 如果我在工厂类中实现 ThreadLocal 会发生什么

标签 java multithreading static factory thread-local

我正在尝试在 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/

相关文章:

java - 从 Facebook Graph 响应中解析 java 中的 JSON 数据

python - 多线程 Python 脚本比非线程脚本花费更长的时间

java - 使 'static' 类可观察

java 静态方法和接口(interface)/继承

java - 如何不抛出一般指定的异常?

java - Spring Batch 需要在一年内每周安排/运行一项作业

java - 某些父实体值无法保存到子实体

c# - 使用 `lock` 比 `SemaphoreSlim` 有什么优势?

java - Spring集成MessageQueue无需轮询

java - 扩展 Java 类还是提供静态帮助类?