`

SimpleDateFormat线程不安全及解决办法

    博客分类:
  • java
 
阅读更多

SimpleDateFormatt线程不安全及解决办法

 

一. 为什么SimpleDateFormat不是线程安全的?

Java源码如下:

 

  1.  
    /**
  2.  
    * Date formats are not synchronized.
  3.  
    * It is recommended to create separate format instances for each thread.
  4.  
    * If multiple threads access a format concurrently, it must be synchronized
  5.  
    * externally.
  6.  
    */
  7.  
    public class SimpleDateFormat extends DateFormat {
  8.  
     
  9.  
    public Date parse(String text, ParsePosition pos){
  10.  
    calendar.clear(); // Clears all the time fields
  11.  
    // other logic ...
  12.  
    Date parsedDate = calendar.getTime();
  13.  
    }
  14.  
    }
  15.  
     
  16.  
     
  17.  
    abstract class DateFormat{
  18.  
    // other logic ...
  19.  
    protected Calendar calendar;
  20.  
    public Date parse(String source) throws ParseException{
  21.  
    ParsePosition pos = new ParsePosition(0);
  22.  
    Date result = parse(source, pos);
  23.  
    if (pos.index == 0)
  24.  
    throw new ParseException("Unparseable date: \"" + source + "\"" ,
  25.  
    pos.errorIndex);
  26.  
    return result;
  27.  
    }
  28.  
    }

如果我们把SimpleDateFormat定义成static成员变量,那么多个thread之间会共享这个sdf对象, 所以Calendar对象也会共享。

 

 

假定线程A和线程B都进入了parse(text, pos) 方法, 线程B执行到calendar.clear()后,线程A执行到calendar.getTime(), 那么就会有问题。

 

二. 解决方案

1.方法内部创建SimpleDateFormat,不管是什么时候,将有线程安全的对象由共享变为私有局部变量都可以避免多线程问题,不过也加重了创建对象的负担,虽然随时创建SimpleDateFormat会造成一定的性能影响,而且会对GC产生一定的压力,但这并不是核心问题,只要能产生正确的结果:
 
  1.  
    public static String format(Date date) {
  2.  
    if (date == null) {
  3.  
    return "";
  4.  
    }
  5.  
    return new SimpleDateFormat(YMD_HYPHEN_PATTERN).format(date);
  6.  
    }
 
 
 
2.将SimpleDateFormat进行同步使用,在每次执行时都对其加锁,这样也会影响性能,想要调用此方法的线程就需要block,当多线程并发量比较大时会对性能产生一定影响;
 
  1.  
    public static String formatDate(Date date)throws ParseException{
  2.  
    synchronized(sdf){
  3.  
    return sdf.format(date);
  4.  
    }
  5.  
    }
  
在任何公共的地方使用该类时,都需要对SimpleDateFormat进行加锁。
 
3.使用ThreadLocal变量,用空间换时间,这样每个线程就会独立享有一个本地的SimpleDateFormat变量;
 
 
  1.  
    private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
  2.  
    @Override
  3.  
    protected DateFormat initialValue() {
  4.  
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  5.  
    }
  6.  
    };
  7.  
     
  8.  
    public static Date parse(String dateStr) throws ParseException {
  9.  
    return threadLocal.get().parse(dateStr);
  10.  
    }
或者
 
 写一个工具类:

 

  1.  
    public class DateUtil {
  2.  
    private static ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
  3.  
     
  4.  
    public static Date parse(String str) throws Exception {
  5.  
    SimpleDateFormat sdf = local.get();
  6.  
    if (sdf == null) {
  7.  
    sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
  8.  
    local.set(sdf);
  9.  
    }
  10.  
    return sdf.parse(str);
  11.  
    }
  12.  
     
  13.  
    public static String format(Date date) throws Exception {
  14.  
    SimpleDateFormat sdf = local.get();
  15.  
    if (sdf == null) {
  16.  
    sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
  17.  
    local.set(sdf);
  18.  
    }
  19.  
    return sdf.format(date);
  20.  
    }
  21.  
    }
  1.  
这样就可以保证每个线程的本地变量都是安全的,不同线程之间并不共享相同的SimpleDateFormat,从而避免了线程安全问题。
 

 

如果需要对性能比较敏感,可以采用这种方式,至少比前两种的速度要快,但是占用内存也会大一点(但也不会多么夸张)。
分享到:
评论

相关推荐

    simpleDateFormat是线程不安全的

    标题指出的"simpleDateFormat是线程不安全的",意味着在多线程环境下,如果多个线程共享同一个`SimpleDateFormat`实例,可能会引发数据不一致或异常。 `SimpleDateFormat`类的线程不安全主要源于以下几个原因: 1....

    SimpleDateFormat线程不安全的5种解决方案.md

    SimpleDateFormat线程不安全的5种解决方案.md

    SimpleDateFormat线程不安全的5种解决方案.docx

    在多线程环境下,SimpleDateFormat 由于其内部状态在格式化过程中可能会被多个线程修改,因此会出现线程不安全的现象。解决这一问题的方法有多种,包括将 SimpleDateFormat 定义为局部变量、使用 synchronized 或 ...

    高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx

    SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...

    详解SimpleDateFormat的线程安全问题与解决方案

    在Java编程中,`SimpleDateFormat`是一个常用的日期时间格式化工具类,但它的设计并不是线程安全的。本文将深入探讨`SimpleDateFormat`的线程安全问题及其解决方案。 ### 1. 线程安全问题的原因 `SimpleDateFormat...

    ThreadLocal:如何优雅的解决SimpleDateFormat多线程安全问题

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug...ThreadLocal注意事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...

    关于SimpleDateFormat的非线程安全问题及其解决方案.docx

    ### 关于SimpleDateFormat的非线程安全问题及其解决方案 #### 一、问题介绍 在Java开发过程中,`SimpleDateFormat`是被广泛使用的日期格式化工具类。然而,在多线程环境下,`SimpleDateFormat`存在非线程安全的...

    深入理解Java:SimpleDateFormat安全的时间格式化

    SimpleDateFormat类不是线程安全的,这意味着在多线程环境下,如果多个线程同时访问同一个SimpleDateFormat实例,可能会导致各种问题,例如转化的时间不正确、报错、线程被挂死等等。 知识点2: 创建...

    Java SimpleDateFormat线程安全问题原理详解

    Java SimpleDateFormat线程安全问题原理详解 Java SimpleDateFormat线程安全问题是Java开发中一个常见的问题。SimpleDateFormat是Java中一个常用的日期时间格式化类,但是它却存在线程安全问题。在多线程环境下,...

    Java多线程环境下SimpleDateFormat类安全转换

    SimpleDateFormat类是Java中常用的日期格式化类,但是它并不是线程安全的。在多线程环境下,如果多个线程同时使用同一个SimpleDateFormat对象,可能会出现日期格式化错误的问题。 2. 使用ThreadLocal解决线程安全...

    由浅入深解析 SimpleDateFormat

    1. SimpleDateFormat 是线程不安全的,因此在多线程环境下使用需要特别注意。 2. 创建 SimpleDateFormat 实例需要消耗大量的资源,因此应当尽量少创建实例。 3. SimpleDateFormat 可以使用 applyPattern 方法修改...

    Java多线程编程的线程安全性.docx

    Java标准库中有一些类,如ArrayList、HashMap和SimpleDateFormat,并未设计为线程安全,因此在多线程环境下直接使用可能导致数据不一致或其他问题。开发者应当了解每个类的线程安全特性,以便做出正确的选择和适当地...

    Java理论与实践:描绘线程安全性

    这类类在设计时就没有考虑线程安全,例如`SimpleDateFormat`,在1.4 JDK之前的版本中并未明确指出其线程不安全,导致许多开发者在并发场景中误用,引发错误。 在文档中清晰地记录类的线程安全性是至关重要的。如...

    有关SimpleDateFormat的常用方法说明

    - `SimpleDateFormat`是线程不安全的,如果在多线程环境中使用,需要考虑同步问题。 - 日期和时间的格式化字符串要与实际情况对应,避免出现理解错误。 以上就是关于`SimpleDateFormat`的一些常见用法和注意事项,...

    java SimpleDateFormat &Calendar

    需要注意的是,由于`SimpleDateFormat`不是线程安全的,所以在多线程环境中,建议为每个线程创建单独的实例。 `Calendar`类则是Java中更底层的日期和时间工具,它提供了一套完整的API来操作日期和时间,包括添加、...

    JavaScript实现的SimpleDateFormat

    在JavaScript中,没有内置的`SimpleDateFormat`类,它是一个Java中的类,用于日期和时间的格式化。然而,由于JavaScript在处理日期时的功能相对有限,开发者常常需要自定义函数或者使用第三方库来实现类似的功能。这...

    Java ThreadLocal 线程安全问题解决方案

    Java中的ThreadLocal是解决线程安全问题的一个重要工具,它提供了一种在多线程环境下为每个线程维护独立变量副本的方法,从而避免了共享状态带来的竞态条件和线程安全问题。 线程安全问题通常由全局变量和静态变量...

    SimpleDateFormat使用详解

    SimpleDateFormat 使用详解 SimpleDateFormat 是 Java 中的一个日期和时间格式化类,它继承自 DateFormat 类。SimpleDateFormat 允许用户以各种方式格式化日期和时间,例如以年、月、日、时、分、秒等不同的格式来...

    DateFormat多线程问题

    Java 8 引入了`java.time.format.DateTimeFormatter`,这个类是线程安全的,可以作为`SimpleDateFormat`的一个更优选择。它提供了与`SimpleDateFormat`类似的功能,但避免了线程安全问题。 5. **池化`DateFormat`...

Global site tag (gtag.js) - Google Analytics