2010-12-08 2 views
21

Мне приходится печатать много форматированных десятичных значений во многих потоках параллельно. Для форматирования десятичных значений я использую java.text.DecimalFormat, настроенный шаблоном. Я знаю предупреждение от Java РОУ DecimalFormat:DecimalFormat.format (double) в разных потоках

десятичных форматы, как правило, не синхронизированы. Рекомендуется создавать отдельные экземпляры формата для каждой нити. Если несколько потоков получают доступ к формату одновременно, он должен быть синхронизированным извне.

Но я не знаю, если это предупреждение относится к моему сценарию: я устанавливаю java.text.DecimalFormat один раз при запуске приложения (и хранить Formatter в конечном поле). После этого я ТОЛЬКО использую метод format(double).

Причина, по которой я хочу это сделать: я не хочу терять производительность, создавая новый экземпляр DecimalFormat каждый раз, когда мне нужно печатать отформатированный номер.

Я посмотрел код DecimalFormat.format(double), и он выглядит потокобезопасным, но я не уверен.

Не могли бы вы подтвердить, что использование DecimalFormat.format(double) в конечном итоге является потокобезопасным, не изменяя конфигурацию форматирования или не объясняя, почему это не так?

+2

А "workarround" является использование ThreadLocal, но есть не вопрос. – Ralph 2010-12-08 12:02:39

+0

Другим обходным решением является синхронизация объекта DecimalFormat при конверсиях. Либо (а) вы делаете несколько преобразований и синхронизации, это не сильно повлияет на производительность, или (б) вы делаете много конверсий, и в этом случае объекты DecimalFormat могут быть повторно использованы для конверсий в одном потоке, поэтому их затраты на строительство должны быть незначительными. – 2010-12-08 12:38:53

ответ

18

Хотя текущая реализация может быть в конечном счете потокобезопасной, нет такой гарантии для будущих реализаций или для других JRE.

Вы подтвердили, что избежать new DecimalFormat() - измеримое усиление производительности в вашем приложении?

+0

В одном тесте я случайно обнаружил, что для создания экземпляра NumberFormat и Decimal формата требуется около 23 мс, что, по-моему, является временем неиспользуемого времени выполнения, любым обходным решением? – 2016-02-03 07:48:25

6

Реализация текущей Hotspot для DecimalFormat делает вызов DecimalFormat.format (double) потокобезопасным, если вы не вызываете другие методы в этом экземпляре. Однако настоятельно рекомендуется не полагаться на это (возможно) временное поведение.

Считаете ли вы использование переменной ThreadLocal, чтобы избежать слишком большого числа new DecimalFormat()?

13

Просто используйте этот поточно-сниппет для NumberFormat:

static ThreadLocal<NumberFormat> numberFormat = new ThreadLocal<NumberFormat>() { 
    @Override 
    public NumberFormat initialValue() { 
     return new DecimalFormat("00000"); 
    } 
}; 

Или в Java 8, как сказал Jesper в комментарии:

private static ThreadLocal<NumberFormat> numberFormatter = 
        ThreadLocal.withInitial(() -> new DecimalFormat("00000"));