关于SimpleDateFormat的一些使用及性能数据

下午在代码review时,和Y同学讨论了SimpleDateFormat的使用,发现自己以前使用有不当的地方,特此记录。


在jdk的doc中指出SimpleDateFormat

Synchronization

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

之前使用的时候,直接new一个,没有考虑到多线程问题,在并发的情况下会有问题。
public static DateFormat dataTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")


考虑到该方法在工程中用的比较多,测试了几种常用方法的性能, 测试场景:单线程多次format , 数据如下:
次数:10w
jdkSimpleDataFormat cost time: 1115ms
apacheSimpleDataFormat cost time: 275ms
threadLocalSimpleDataFormat cost time: 183ms

次数:100w
jdkSimpleDataFormat cost time: 4737ms
apacheSimpleDataFormat cost time: 1572ms
threadLocalSimpleDataFormat cost time: 853ms

次数:1000w
jdkSimpleDataFormat cost time: 35170ms
apacheSimpleDataFormat cost time: 14078ms
threadLocalSimpleDataFormat cost time: 8509ms

从数据可以看出
(1) apache common-lang提供的DateFormatUtils.format方法比JDK提供的SimpleDataFormat.format性能高出 149.82%
(2) ThreadLocal方式比
DateFormatUtils.format 方式性能高出 65.44%

结论:在使用SimpleDataFormat时,尽量使用ThreadLocal 方式。


测试代码如下,有兴趣的同学可以测下多线程情形下的性能数据。
package com.bc.perf;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.apache.commons.lang.time.DateFormatUtils;

public class SimpleDataFormatPerfTest {
    
     private static final int circleNum = 10000000;
     private static String pattern = "yyyy-MM-dd HH:mm:ss";
    
     private Executor testExecutor = Executors.newFixedThreadPool(64);
    
     private static ThreadLocal<SimpleDateFormat> simpleDateFormatProvider = new ThreadLocal<SimpleDateFormat>() {
          @Override
          protected SimpleDateFormat initialValue() {
               return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          }
     };
    
    
     public static void main(String[] args){
          SimpleDataFormatPerfTest test = new SimpleDataFormatPerfTest();
         
          SimpleDateFormat format = new SimpleDateFormat(pattern);
          System.out.println("jdkSimpleDataFormat date format: " + format.format(new Date()));
         
          System.out.println("apacheSimpleDataFormat date format: " + DateFormatUtils.format(new Date(), pattern));
         
          System.out.println("threadLocalSimpleDataFormat date format: " + simpleDateFormatProvider.get().format(new Date()));
         
          //1 Jdk SimpleDateFormat
          test.jdkSimpleDataFormatPerf();
          //2 Apache common-lang SimpleDateFormat
          test.apacheSimpleDataFormatPerf();
          //3 ThreadLocal SimpleDateFormat
          test.threadLocalSimpleDataFormatPerf();
     }
    
     public void jdkSimpleDataFormatPerf() {
          long t1 = System.currentTimeMillis();

          for (int i = 0; i < circleNum; i++) {
               SimpleDateFormat format = new SimpleDateFormat(pattern);
               format.format(new Date());
          }

          long t2 = System.currentTimeMillis();
          System.out.println("originSimpleDataFormat cost time: " + (t2 - t1));

     }
    
     public void apacheSimpleDataFormatPerf() {
          long t1 = System.currentTimeMillis();

          for (int i = 0; i < circleNum; i++) {
               DateFormatUtils.format(new Date(), pattern);
          }

          long t2 = System.currentTimeMillis();
          System.out.println("apacheSimpleDataFormat cost time: " + (t2 - t1));

     }
    
     public void threadLocalSimpleDataFormatPerf() {
          long t1 = System.currentTimeMillis();
         
          for (int i = 0; i < circleNum; i++) {
               simpleDateFormatProvider.get().format(new Date());
          }
         
          long t2 = System.currentTimeMillis();
          System.out.println("threadLocalSimpleDataFormat cost time: " + (t2 - t1));
     }
}




 

posted @ 2013-06-10 20:19  爱生活,爱编程  阅读(927)  评论(0编辑  收藏  举报