zoukankan      html  css  js  c++  java
  • JDK中的SimpleDateFormat线程非安全

      在JDK中使用SimpleDateFormat的时候都会遇到线程安全的问题,在JDK文档中也说明了该类是线程非安全的,建议对于每个线程都创建一个SimpleDateFormat对象。如下面一个Case中,多个线程去调用SimpleDateFormat中得parse方法:

    @Test
        public void testUnThreadSafe() throws Exception {
            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,S");
    
            final String[] dateStrings = {
                    "2014-04-30 18:51:01,61",
                    "2014-04-30 18:51:01,461",
                    "2014-04-30 18:51:01,361",
                    "2014-04-30 18:51:01,261",
                    "2014-04-30 18:51:01,161",
            };
            int threadNum = 5;
            Thread[] parseThreads = new Thread[threadNum];
            for (int i=0; i<threadNum; i++) {
               parseThreads[i] = new Thread(new Runnable() {
                   public void run() {
                       for (int j=0; j<dateStrings.length; j++) {
                           try {
                               System.out.println(Thread.currentThread().getName() + " " + sdf.parse(dateStrings[j]));
                           } catch (ParseException e) {
                               e.printStackTrace();
                           }
                       }
                   }
               });
               parseThreads[i].start();
            }
    
            for (int i=0; i<threadNum; i++) {
                parseThreads[i].join();
            }
        }

    将会抛出异常:java.lang.NumberFormatException: multiple points

    通常的解决办法有:

    1. 使用synchronized

    synchronized (sdf) {
      System.out.println(Thread.currentThread().getName() + " " + sdf.parse(dateStrings[j]));
    }

    2. 每用一次实例化一次

    try {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,S");
        System.out.println(Thread.currentThread().getName() + " " + sdf.parse(dateStrings[j]));
    } catch (ParseException e) {
        e.printStackTrace();
    }

    3. 使用ThreadLocal

        @Test
        public void testUnThreadSafe() throws Exception {
    //        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,S");
            final ThreadLocal<SimpleDateFormat> localSdf = new ThreadLocal<SimpleDateFormat>();
            final String[] dateStrings = {
                    "2014-04-30 18:51:01,61",
                    "2014-04-30 18:51:01,461",
                    "2014-04-30 18:51:01,361",
                    "2014-04-30 18:51:01,261",
                    "2014-04-30 18:51:01,161",
            };
            int threadNum = 5;
            Thread[] parseThreads = new Thread[threadNum];
            for (int i=0; i<threadNum; i++) {
               parseThreads[i] = new Thread(new Runnable() {
                   public void run() {
                       for (int j=0; j<dateStrings.length; j++) {
                           try {
                               SimpleDateFormat sdf = localSdf.get();
                               if (sdf == null) {
                                   sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,S");
                                   localSdf.set(sdf);
                               }
                               System.out.println(Thread.currentThread().getName() + " " + sdf.parse(dateStrings[j]));
                           } catch (ParseException e) {
                               e.printStackTrace();
                           }
                       }
                   }
               });
               parseThreads[i].start();
            }
    
            for (int i=0; i<threadNum; i++) {
                parseThreads[i].join();
            }
        }

    第一种和第二种解决方案对于一个工具类来说都会带来昂贵的资源开销,建议使用ThreadLocal创建一个对单个线程来说全局的变量,保证线程安全,当然可以使用第三方工具类如Apache commons 里的FastDateFormat或者Joda-Time类库来处理。

  • 相关阅读:
    CSS学习笔记07 盒子模型
    [Android]AndFix使用说明
    [Android]自定义控件LoadMoreRecyclerView
    [算法]Plus One
    [Android]android Service后台防杀
    [Android]android studio预览视图时报错
    [算法]删除无序单链表中值重复出现的节点
    [算法] 将单链表的每K个节点之间逆序
    [Android]热修复框架AndFix测试说明
    [算法]单链表的选择排序
  • 原文地址:https://www.cnblogs.com/nexiyi/p/SimpleDateFormat_ThreadSafe_Solution.html
Copyright © 2011-2022 走看看