`
lichaozhangobj
  • 浏览: 100877 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转:使用SimpleDateFormat必须注意的问题

    博客分类:
  • java
阅读更多

在使用SimpleDateFormat的经常会有一些错误的用法,例如如下方式:

public class TestDateFormat{
     
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
     
public void method1(){
         sdf.format(
new Date());
     }

     
public void method2(){
         sdf.format(
new Date());
     }

 )

为了渐少new 的次数而把SimpleDateFormat做成成员或者静态成员,但这样的做法是隐含着错误的,是不安全
 的。如下给出证明:

 import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class TestDateFormat{
    
private SimpleDateFormat sdf ;
    
public static void main(String[] args) {
        SimpleDateFormat sdf
= new SimpleDateFormat("yyyy-MM-dd");
        Date date1 
= new Date();
        Date date2 
= new Date(date1.getTime()+1000*60*60*24);
        System.out.println(date1);
        System.out.println(date2);
        Thread thread1 
= new Thread(new Thread1(sdf,date1));
        thread1.start();
        Thread thread2 
= new Thread(new Thread2(sdf,date2));
        thread2.start();
    }

    
}

class Thread1 implements Runnable{
    
private SimpleDateFormat sdf;
    
private Date date;
    
public Thread1(SimpleDateFormat sdf,Date date){
        
this.sdf = sdf;
        
this.date = date;
    }

    
public void run() {
        
for(;;){
            String strDate 
= sdf.format(date);
            
if("2007-02-27".equals(strDate)){
                System.err.println(
"Error: date1="+strDate);
                System.exit(
0);
            }

        }

    }

}

class Thread2 implements Runnable{
    
private SimpleDateFormat sdf;
    
private Date date;
    
public Thread2(SimpleDateFormat sdf,Date date){
        
this.sdf = sdf;
        
this.date = date;
    }

    
public void run() {
        
for(;;){
            String strDate 
= sdf.format(date);
            
if("2007-02-26".equals(strDate)){
                System.err.println(
"Error: date1="+strDate);
                System.exit(
0);
            }

        }

    }

}

很快,基本几十次就会出现错误。错误原因:
 因为SimpleDateFormat处理复杂,Jdk的实现中使用了成员变量来传递参数,这个就造成在多线程的时候
 会出现错误。上边的程序证明了这个问题。

再看看SimpleDateFormat的Jdk 的Source,有这么一段注释,说明它不是线程安全的。
 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
 
 继续看看Sun自己的网站上。在sun的bug database中
 Bug ID:  4228335  讲的就是这个问题。
 SimpleDateFormat is not threadsafe (one more try)
 其中有这么几段话值得关注:
 1,
 Aside from the obvious, there are two reasons why this fix should be made:
- The documentation for DateFormat states that a DateFormat object should be used
multiple times, implying that construction is expensive.  Furthermore,
 no mention is made of SimpleDateFormat's lack of thread-safety. 
 Since for most applications the date formats remain constant,
 it is very easy to conclude that DateFormats should be application globals.
 But SimpleDateFormat produces incorrect results when used in this way.
- Bug 4101500, a similar problem with NumberFormat, was fixed.

建议修改这个问题,而且NumberFormat已经修改,解决了这个问题。简单测试了一下NumberFormat确是不出错

2,
Use of a cloned Calendar object in format(), as suggested in JDC comments,
slows down the execution 30-50%. And it potentially affects footprint because
of cloned objects. Another approach would be to have a Calendar instance per
thread. However, this approach will cause problems at the API semantic level due
to the get/setCalendar methods.
这一段解释了为什么没修改这个问题,一个是保持API不变,另一个是因为Clone比new慢,会损失效率。

结论:每次使用它的时候现new,或者用一个同步函数把new好的包装起来使用吧。

 

分享到:
评论

相关推荐

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

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...

    有关java中的Date,String,Timestamp之间的转化问题

    Java 中的 Date、String 和 Timestamp 之间的转换问题 Java 中的日期和时间处理是编程中非常重要的一方面,Date、String 和 ...Java 中的日期和时间处理需要注意不同类型之间的转换问题,以避免出现奇怪的结果。

    java数据类型转换.pdf

    - 时间日期转换:使用SimpleDateFormat类进行日期字符串与日期对象的转换,如`SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse(dateStr);` 理解并熟练掌握这些转换技巧,可以...

    java SimpleDateFormat &Calendar

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

    JAVA使用SimpleDateFormat类表示时间代码实例

    需要注意的是,在使用 SimpleDateFormat 对象的 parse() 方法时可能会出现转换异常,即 ParseException,因此需要进行异常处理。 JAVA 中的日期和时间处理可以使用 Date 类和 SimpleDateFormat 类来实现,通过 ...

    Java中SimpleDateFormat日期格式转换详解及代码示例

    在上面的代码示例中,我们使用了SimpleDateFormat将日期类型时间转换为字符串类型时间,并将字符串类型时间转换回日期类型时间。同时,我们也演示了如何使用SimpleDateFormat的常用格式定义来实现日期格式转换。 ...

    Java时间转换

    在Java时间转换中,还需要注意一些特殊的情况,例如将日期和时间转换为字符串时,需要注意字母y的大小写问题。在Java中,如果日期和时间格式中包含字母y,例如"yyyyMMdd",那么字母y不能大写,否则将导致日期和时间...

    JAVA类型转换[文].pdf

    例如,可以使用`SimpleDateFormat`进行日期字符串和日期对象之间的转换。 在编程实践中,合理使用类型转换能提高代码的灵活性和可读性。然而,需要注意的是,强制类型转换可能导致数据丢失或异常,因此在转换时要...

    日期格式转换的Java实现

    但是,通常我们不直接使用`DateFormat`类,而是使用其子类`SimpleDateFormat`,因为它提供了更多的灵活性。 #### 2. `SimpleDateFormat`类详解 `SimpleDateFormat`是`DateFormat`的一个子类,它可以让我们根据...

    Java中的SimpleDateFormat使用详解

    需要注意的是,`SimpleDateFormat`不是线程安全的,因此在多线程环境中使用时,要么为每个线程创建独立的实例,要么使用`ThreadLocal`来存储实例。 此外,`SimpleDateFormat`也存在一些效率问题,因为它的解析过程...

    java日期格式化SimpleDateFormat的使用详解

    java 日期格式化 SimpleDateFormat 的使用详解 java 中的日期格式化是通过 ...需要注意的是,在使用 SimpleDateFormat 时,需要注意日期和时间模式字符串的大小写,因为不同的模式字母具有不同的含义。

    Java时间格式转化

    1. **线程安全问题**:`SimpleDateFormat`不是线程安全的,在多线程环境中应该避免共享实例,或者使用`ThreadLocal`来管理。 2. **异常处理**:在进行字符串到`Date`的转换时,一定要注意捕获并处理`ParseException`...

    SimpleDateFormate格式说明.txt

    1. **格式化与解析**:`SimpleDateFormat`提供了一种方便的方式来格式化和解析日期,但需要注意的是,它不是线程安全的,如果在多线程环境中使用,应该考虑使用线程安全的`DateTimeFormatter`类。 2. **国际化问题**...

    java代码-SimpleDateFormat YYYY解析问题

    在标题和描述中提到的 "YYYY" 解析问题,通常指的是在使用 `SimpleDateFormat` 进行日期解析时遇到的困惑或错误。 首先,我们需要明确 `YYYY` 和 `yyyy` 在 `SimpleDateFormat` 中的区别。`yyyy` 是一个代表年份的...

    java中int_char_string三种类型的相互转换

    需要注意的是,任何类型都可以使用 toString() 方法转换成 String 类型。 十、时间的处理 在 Java 中,时间的处理可以使用 SimpleDateFormat 对象。例如: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM...

    java 时间转换(转载)

    - `String`到`Date`:使用`SimpleDateFormat`的`parse`方法,但需要注意异常处理。 - `Date`到`LocalDateTime`:通过`Instant`和`ZoneId`转换,`date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime...

    JAVA获取当前时间并转换成string格式

    需要注意的是,SimpleDateFormat 的格式字符串 "yyyy/MM/dd HH:mm:ss" 可以根据需要进行修改。例如,如果我们想将日期和时间格式化为 "yyyy年MM月dd日 HH:mm:ss",那么我们可以将格式字符串修改为 "yyyy年MM月dd日 ...

    时间转换类.docx

    1. **定义日期格式**:使用`SimpleDateFormat`类定义日期的格式,这里的格式为`"yyyy-MM-dd"`,其中`yyyy`表示四位数的年份,`MM`表示月份,`dd`表示具体日期。 2. **日期解析**:通过`SimpleDateFormat`的`parse...

    时间日期转换

    - 在使用 `SimpleDateFormat` 进行日期格式化或解析时,需要确保所使用的日期格式字符串是正确的,否则会抛出异常。 - 如果需要处理多种不同的日期格式,可以通过创建多个 `SimpleDateFormat` 实例来实现。 - 在处理...

Global site tag (gtag.js) - Google Analytics