1

考虑以下类:

public class Money {
    private double amount;

    public Money(double amount) {
        super();
        this.amount = amount;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public Money multiplyBy( int factor) {
        this.amount *= factor;
        return this;
    }
}

我可以采取哪些预防措施来确保此类在多线程方面没有任何问题。有良好的表现。同时确保货币精度不会成为问题

4

4 回答 4

0

有几个关键点可以使 POJO(普通旧 Java 对象)线程安全:

  1. 使类不可变。如果添加任何实例变量,请将它们设为 final 或 volatile。

  2. 使您的 getter 和 setter 同步,即

    public synchronized void setAmount(double amount) {}
    
于 2018-09-26T17:09:48.477 回答
0

理想情况下,如果您将类设为不可变,则不必为多线程而烦恼。但是在这里,您应该将 multiplyBy 方法设置为相互可执行的,这样它就不会出现不一致的行为。此外,您不需要提供 setter,因为唯一的构造函数将数量作为参数。

于 2018-09-26T17:14:17.330 回答
0

艾哈迈德,你的问题是模棱两可的。

关于多线程:不清楚多线程问题是什么意思。例如,该类在同步良好的意义上对多线程没有任何问题,但是您仍然可以将 Money 对象的状态设置为混乱,由多个线程使用它:

public class Money {
    private volatile double amount;

    public Money(double amount) {
        super();
        this.amount = amount;
    }

    public double getAmount() {
        return amount;
    }

    public synchronized void setAmount(double amount) {
        this.amount = amount;
    }

    public synchronized Money multiplyBy( int factor) {
        this.amount *= factor;
        return this;
    }
}

关于货币精度:正如 Andreas 回答的那样,请参阅:为什么不使用 Double 或 Float 来表示货币?. 还有一个可能很有趣:在 Java 应用程序中用于赚钱的最佳数据类型是什么?

于 2018-09-26T17:52:16.637 回答
0

保持精度

有几种方法可以保持精度。第一个是完全避免像s 和s这样的固定精度浮点二进制数类型floatdouble,如果您的货币使用超过该点的十进制数字。以下是一些不错的选择:

BigDecimal

java.math.BigDecimal允许您轻松存储精确的有限长十进制值,但它可能有点慢。

BigDecimal如果您需要简单的编程和精确的结果,请使用s,但您可以接受缓慢。

long

long如果您使用的是美元,则可以使用美分而不是美元来存储金额。

对于其他货币,您可以取货币面额的理性 GCD 的倒数,并在存储时乘以一切。

使困惑?这是 Wolfram|Alpha 的一个示例,它通过所有艰苦的工作从可用的美元面额(1/100 美元到 100 美元)中找出它应该将美元乘以 100。确保使用分数而不是小数。

long如果您需要很高的速度并且可以接受大于 92,233,720,368,547,758.07 美元的货币金额会给出完全错误的结果的缺点,请使用 s 。

除了自身速度快之外,longs 还使用更少的内存并且从不需要自己的垃圾收集,所以这对它们来说是另一个小的加速。

BigInteger

longs 可以替换为java.math.BigIntegers以避免任何溢出问题。

如果您想要介于其他两者的速度和缓慢之间且没有合理机会溢出的情况,请使用此选项。

于 2018-09-26T22:46:20.210 回答