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

    (一)引子

    最近看公司同事写的日期格式化代码:

     public static  String formatDate(Date date)throws ParseException{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(date);
     }
    

     就想起之前所学到的,SimpleDateFormat是线程不安全的。

    此处的代码也印证了之前所学,所以同事的代码每次都新new一个SimpleDateFormat。

    虽然不高明,但杜绝了安全隐患。

    更甚一步,觉得自己应该详细读下其源码,理解它在哪一点上不安全。

    (二)如何不安全

    看format的源码,一段代码跃然纸上:

     1 private StringBuffer format(Date date, StringBuffer toAppendTo,
     2                                 FieldDelegate delegate) {
     3         // Convert input date to time field list
     4         calendar.setTime(date);
     5 
     6         boolean useDateFormatSymbols = useDateFormatSymbols();
     7 
     8         for (int i = 0; i < compiledPattern.length; ) {
     9             int tag = compiledPattern[i] >>> 8;
    10             int count = compiledPattern[i++] & 0xff;
    11             if (count == 255) {
    12                 count = compiledPattern[i++] << 16;
    13                 count |= compiledPattern[i++];
    14             }
    15 
    16             switch (tag) {
    17             case TAG_QUOTE_ASCII_CHAR:
    18                 toAppendTo.append((char)count);
    19                 break;
    20 
    21             case TAG_QUOTE_CHARS:
    22                 toAppendTo.append(compiledPattern, i, count);
    23                 i += count;
    24                 break;
    25 
    26             default:
    27                 subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
    28                 break;
    29             }
    30         }
    31         return toAppendTo;
    32     }

    第四行代码 calendar.setTime(date) 缓存了时间在成员变量calendar中,而subFormat又使用了calendar

    所以多个线程调用SimpleDateFormat时,共用变量calendar,互相影响。

    (三)验证下其不安全

    验证代码如下——

    package com.concurrent;
    
    import java.text.ParseException;
    import java.util.Date;
    
    /**
     * Created by baimq on 2018/1/10.
     */
    public class SimpleDateFormatTest {
    
    
        public static class TestSimpleDateFormatThreadSafe extends Thread {
            @Override
            public void run() {
                while(true) {
                    try {
                        this.join(2000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try {
                        System.out.println(this.getName()+":"+new Date()+":"+ DateUtil.parse("2018-01-10 22:00:20"));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
        public static void main(String[] args) {
            for(int i = 0; i < 3; i++){
                new TestSimpleDateFormatThreadSafe().start();
            }
    
        }
    
    }

    (四)如何安全

    (1)每次使用时new一个SimpleDateFormat

    好处是线程安全,代码简单

    坏处是开销大

    (2)使用theadlocal

    其原理是,每次使用时复制一份SimpleDateFormat,所以不会有线程安全问题

    代码如下——

     private static  ThreadLocal<SimpleDateFormat> threadLocalSDF = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }
        };
    
        public static  String formatDate(Date date)throws ParseException{
            return threadLocalSDF.get().format(date);
        }

    (3)在博客园里还见到其它方案

      1.使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。

      2.使用Joda-Time类库来处理时间相关问题

  • 相关阅读:
    如何入门深度学习?
    java opencv使用相关
    python操作Excel读写--使用xlrd
    从声学模型算法总结 2016 年语音识别的重大进步丨硬创公开课
    sift 与 surf 算法
    BP神经网络原理详解
    Nature重磅:Hinton、LeCun、Bengio三巨头权威科普深度学习
    浅谈流形学习(转)
    远离神经网络这个黑盒,人工智能不止这一条路可走
    对比深度学习十大框架:TensorFlow 并非最好?
  • 原文地址:https://www.cnblogs.com/baimingqian/p/8260995.html
Copyright © 2011-2022 走看看