多线程,性能和精度考虑

时间:2018-09-26 17:05:35

标签: java multithreading precision currency money-format

请考虑以下课程:

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 个答案:

答案 0 :(得分:0)

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

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

  2. 使您的吸气剂和设置器同步,即

    public synchronized void setAmount(double amount) {}
    

答案 1 :(得分:0)

理想情况下,如果您将一个类设为不可变的,则不必担心多线程。但是在这里,您应该使multipleBy方法可以相互执行,以便它不会出现不一致的行为。 另外,您无需提供设置器,因为唯一的构造函数将数量作为参数。

答案 2 :(得分: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回答的那样,请参阅:Why not use Double or Float to represent currency?。同样可能很有趣:What is the best data type to use for money in Java app?

答案 3 :(得分:0)

保持精度

有几种保持精度的方法。第一种是完全避免使用floatdouble s这样的定精度浮点二进制数类型(如果您的货币使用的是十进制数字)。这里有一些不错的选择:

BigDecimal

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

如果您需要简化编程和精确计算结果,请使用BigDecimal,但是您可以放慢速度。

long

long可用于以美分而不是美元来存储金额。如果您使用的是美国货币。

对于其他货币,您可以获取货币面额的有理GCD的倒数,然后在存储时将所有乘以该值。

困惑吗?这是an example of Wolfram|Alpha doing all the hard work of figuring out from the available US currency denominations ($1/100 through $100) that it should multiply US currency by 100。确保使用分数而不是小数。

如果您需要非常快的速度并且可以接受long,则缺点是货币金额大于92,233,720,368,547,758.07美元会得出完全错误的结果。

long除了自身速度很快之外,还使用了更少的内存,并且从不需要垃圾收集,因此这对他们来说又是一个很小的提速。

BigInteger

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

如果您希望在其他两个的速度和速度之间保持某种速度,而又没有合理的机会发生溢出,请使用此功能。