многопоточность, производительность и точность - PullRequest
0 голосов
/ 26 сентября 2018

рассмотрим следующий класс:

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 голосов
/ 27 сентября 2018

Поддержание точности

Существует несколько способов поддержания точности.Во-первых, полностью избегает типов двоичных чисел с плавающей точкой фиксированной точности, таких как float s и double s , если ваша валюта использует десятичные цифры после точки.Вот несколько хороших альтернатив:

BigDecimal

java.math.BigDecimal позволяет с легкостью хранить точные конечные десятичные значения, но это может быть немногомедленно.

Используйте BigDecimal s, если вам нужно, чтобы программирование было легким, а результаты - точными, но с медлительностью все в порядке.

long

long можно использовать для хранения суммы в центах, а не в долларах, если вы используете валюту США.

Для других валют вы можете взять обратную величину рационального GCD для деноминаций и умножить всекогда вы его сохраните.

В замешательстве?Вот пример того, как Wolfram | Alpha проделала всю тяжелую работу по выяснению по имеющимся номиналам американской валюты (от 1/100 до 100 долларов), что она должна умножить валюту США на 100 .Обязательно используйте дроби, а не десятичные дроби.

Используйте long s, если вам нужна большая скорость и вы согласны с тем недостатком, что денежные суммы, превышающие 92 233 720 368 547 758,0 долл. США, дают совершенно неверные результаты.

Помимо того, что они быстрые сами по себе, long также используют намного меньше памяти и никогда не требуют сборки мусора сами по себе, так что это еще одно небольшое ускорение для них.

BigInteger

long s можно заменить на java.math.BigInteger s , чтобы избежать каких-либо проблем переполнения.

Используйте это, если вы хотите что-то между скоростью и медлительностью двух других без достаточных шансовкогда-либо переполнен.

0 голосов
/ 26 сентября 2018

В идеале, если вы делаете класс неизменным, вам не нужно беспокоиться о многопоточности.Но здесь вы должны сделать метод multiplyBy взаимно исполняемым, чтобы он не имел противоречивого поведения.Кроме того, вам не нужно указывать setter, поскольку единственный конструктор принимает значение в качестве аргумента.

0 голосов
/ 26 сентября 2018

Ахмад, ваш вопрос неоднозначен.

О многопоточности: Не совсем понятно, что вы имеете в виду под проблемами с многопоточностью.Например, у этого класса нет проблем с многопоточностью в том смысле, что он хорошо синхронизирован, но вы все равно можете установить состояние объекта 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;
    }
}

О точности денег: Как ответил Андреас, см .: Почему бы не использовать Double или Float для представления валюты? .Также это может быть интересно: Какой тип данных лучше всего использовать для денег в приложении Java?

0 голосов
/ 26 сентября 2018

Есть пара ключевых моментов, чтобы сделать поток POJO (Plain Old Java Object) безопасным:

  1. Сделать класс неизменным.Если вы добавляете какие-либо переменные экземпляра, делайте их либо окончательными, либо переменными.

  2. Синхронизируйте ваши геттеры и сеттеры, то есть

    public synchronized void setAmount(double amount) {}
    
...