gpt4 book ai didi

java - NumberFormat/DecimalFormat 的线程安全动态模式

转载 作者:行者123 更新时间:2023-12-02 08:47:31 34 4
gpt4 key购买 nike

在网络上找不到合适的解决方案,因此我想问问我使用java格式的方式是否正确。

1)在 NumberFormat.java 文档中它说

Number formats are generally not synchronized. It is recommended to create separate format instances for each thread.

我们一直在多线程环境中使用格式对象(静态初始化),到目前为止没有任何问题。是否可能是因为一旦定义了格式,我们的状态就不会改变(即,之后不会调用任何 setter )

2)我现在需要定义一种新格式,该格式应在逗号后输出一个或两个有效数字,具体取决于一些额外的逻辑。我这样做的方法是定义一个新的格式包装器,并根据覆盖的 #format(double, StringBuffer, FieldPosition) 方法中的情况委托(delegate)给两个不同的 DecimalFormat。这是代码:

private final NumberFormat FORMAT = new DecimalFormat() {
private final NumberFormat DECIMAL_FORMAT = new DecimalFormat("0.##");
private final NumberFormat DECIMAL_FORMAT_DIGIT = new DecimalFormat(
"0.0#");
public StringBuffer format(double number, StringBuffer result, java.text.FieldPosition fieldPosition) {
if ((number >= 10 && Math.ceil(number) == number)) {
return DECIMAL_FORMAT.format(number, result, fieldPosition);
} else {
return DECIMAL_FORMAT_DIGIT.format(number, result, fieldPosition);
}
}
};

这是最佳实践吗?我担心实际上没有使用包装类(它仅用于遵守 NumberFormat 接口(interface)并委托(delegate)内部格式的所有工作)。我不想调用 DecimalFormat#applyPattern() 因为我认为这会损害不稳定的并发性。

谢谢

最佳答案

  1. We have been using format objects (statically initialized) in a multi-threaded environment with no issues so far. Is it maybe because once the formats are defined, we their state is not changed (ie, no setters are called afterwards)

不可能确切地说出您没有看到任何问题的原因,因为我们不知道您到底如何使用它们。从我的角度来看,可能有以下几个原因:

  • 您没有访问 DecimalFormat 中使用可变实例变量的任何代码路径;
  • 您“碰巧”应用了互斥,因此您永远不会同时在多个线程中使用该实例;
  • 您使用的实现实际上可以正确同步(请注意,Javadoc 说的是“通常不同步”,而不是“从不同步”);
  • 您实际上遇到了问题,但您只是没有充分监控它们;
  • 等等

正如我昨天看到其他人评论的那样,关于同步问题的问题是,如果不同步,则不能保证会看到问题;只是不保证您也看不到它们。

关键是,如果您不应用同步,您就会受到许多您可能完全没有意识到的微妙变化的影响。今天有效,明天就无效;您将有一项全能的工作来找出原因。

  1. Is it the best practice?

我在这里可以想到几个问题:

  1. 通过扩展类(class),您可能会违反fragile base class problem .

    简而言之,除非您实际上显式调用 DecimalFormat 实例上的 public StringBuffer format(double, StringBuffer, java.text.FieldPosition ) 方法,否则您可以无法可靠地知道您的重写方法是否实际上是被调用的方法:对基类 (DecimalFormat) 实现的更改可能会更改您调用该方法所依赖的逻辑。

  2. 您有三个可变实例 - FORMATDECIMAL_FORMATDECIMAL_FORMAT_DIGIT - 它们具有各种方式的 setter 来更改其行为。

    应该将所有这些 setter 传播到所有实例,以便它们的行为一致,例如如果您对 FORMAT 调用 setPositivePrefix,您还应该对 DECIMAL_FORMATDECIMAL_FORMAT_DIGIT 调用相同的方法。

除非您确实需要将 FORMAT 作为参数传递给方法,否则如果您只是定义一个调用您的逻辑的普通旧方法,那么它会更加健壮:基本上,移动您所在的方法重写匿名子类:

private static StringBuffer formatWithSpecialLogic(double number, StringBuffer result, java.text.FieldPosition fieldPosition) {

然后,如果您想使用该特殊逻辑,您必须显式调用该方法。

关于java - NumberFormat/DecimalFormat 的线程安全动态模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37521746/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com