代码之家  ›  专栏  ›  技术社区  ›  Vishal

将DecimalFormat与ThreadLocal一起使用会对性能产生什么影响?

  •  1
  • Vishal  · 技术社区  · 7 年前

    我有一个使用 DecimalFormat https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html )API。

    解决方案1 十进制格式 不是 ThreadLocal 对于 十进制格式

    private static final ThreadLocal<DecimalFormat> restrictTo1DecimalPlace =
                ThreadLocal.withInitial
                        (() -> new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));
    

    解决方案2 :另一个简单的解决方案是放弃对象的可重用性,并创建 十进制格式

    new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(decimalValueToFormat)
    

    什么更好?

    2 回复  |  直到 7 年前
        1
  •  3
  •   meriton    7 年前

    在大多数应用程序中,差异无关紧要,因此您需要更简单的选项。

    您可以通过对两种备选方案进行基准测试来验证这一点:

    public abstract class Benchmark {
    
        public static void main(String[] args) throws Exception {
            final ThreadLocal<DecimalFormat> restrictTo1DecimalPlace =
                    ThreadLocal.withInitial
                            (() -> new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));            
            Benchmark[] marks = {
                new Benchmark("ThreadLocal") {
                    @Override
                    protected Object run(int iterations) throws Throwable {
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < iterations; i++) {
                            sb.append(restrictTo1DecimalPlace.get().format(i * 0.01));
                        }
                        return sb;
                    };
                },
                new Benchmark("new Format") {
                    @Override
                    protected Object run(int iterations) throws Throwable {
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < iterations; i++) {
                            sb.append(new DecimalFormat("0.0%", DecimalFormatSymbols.getInstance(Locale.ENGLISH)).format(i * 0.01));
                        }
                        return sb;
                    };
                },
            };
            for (Benchmark mark : marks) {
                System.out.println(mark);
            }
        }
    
        final String name;
    
        public Benchmark(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return name + "\t" + time() + " ns / iteration";
        }
    
        private BigDecimal time() {
            try {
                // automatically detect a reasonable iteration count (and trigger just in time compilation of the code under test)
                int iterations;
                long duration = 0;
                for (iterations = 1; iterations < 1_000_000_000 && duration < 1_000_000_000; iterations *= 2) {
                    long start = System.nanoTime();
                    run(iterations);
                    duration = System.nanoTime() - start;
                }
                return new BigDecimal((duration) * 1000 / iterations).movePointLeft(3);
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * Executes the code under test.
         * @param iterations
         *            number of iterations to perform
         * @return any value that requires the entire code to be executed (to
         *         prevent dead code elimination by the just in time compiler)
         * @throws Throwable
         *             if the test could not complete successfully
         */
        protected abstract Object run(int iterations) throws Throwable;
    }
    

    在我的机器上,这个打印:

    ThreadLocal 260.132 ns / iteration
    new Format  363.199 ns / iteration
    

    因此,从ThreadLocal获取格式或创建新格式之间的差异约为0.0000001秒。除非应用程序每秒格式化数百万个字符串,否则这不值得考虑:-)

        2
  •  0
  •   ApriOri    7 年前

    我想知道是否有显著差异

    但新的DecimalFormat的分配确实会对内存产生影响,这也可能会消耗时间。 创建新实例是非常合理的,java代码就是这样工作的。

    object pool .