zoukankan      html  css  js  c++  java
  • Call to static DateFormat

    Bug: Call to method of static java.text.DateFormat
    Pattern id: STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE, type: STCAL, category: MT_CORRECTNESS

    As the JavaDoc states, DateFormats are inherently unsafe for multithreaded use. The detector has found a call to an instance of DateFormat that has been obtained via a static field. This looks suspicous.

    For more information on this see Sun Bug #6231579 and Sun Bug #6178997.

     

        上面的英文解释其实应该说得比较清楚,在Java文档中,已经明确说明了DateFormats 是非线程安全的,而在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中,Sun Bug #6231579Sun Bug #6178997都可以印证这个问题。

        导致SimpleDateFormat出现多线程安全问题的原因,是因为:SimpleDateFormat处理复杂,Jdk的实现中使用了成员变量来传递参数,这就造成在多线程的时候会出现错误。

        而Findbugs所说的“Call to static DateFormat”,其实就是一些人:为了渐少new 的次数而把SimpleDateFormat做成成员或者静态成员,上面已经说了,这样做是不安全的。

        其实,出现这种问题的代码一般都长得差不多,典型的代码示例如下:

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

    再给个详细例子说明问题,看下面代码:

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

    public class Test{
    private SimpleDateFormat dateFormat ;
    public static void main(String[] args) {
    SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
    Date today = new Date();
    Date tomorrow = new Date(today.getTime()+1000*60*60*24);
    System.out.println(today); // 今天是2010-01-11 System.out.println(tomorrow); // 明天是2010-01-11 Thread thread1 = new Thread(new Thread1(dateFormat,today));
    thread1.start();
    Thread thread2 = new Thread(new Thread2(dateFormat,tomorrow));
    thread2.start();
    }

    }
    class Thread1 implements Runnable{
    private SimpleDateFormat dateFormat;
    private Date date;
    public Thread1(SimpleDateFormat dateFormat,Date date){
    this.dateFormat = dateFormat;
    this.date = date;
    }
    public void run() {
    for(;;){// 一直循环到出问题为止吧。 String strDate = dateFormat.format(date); // 如果不等于2010-01-11,证明出现线程安全问题了!!!! if(!"2010-01-11".equals(strDate)){
    System.err.println("today="+strDate);
    System.exit(0);
    }
    }
    }
    }
    class Thread2 implements Runnable{
    private SimpleDateFormat dateFormat;
    private Date date;
    public Thread2(SimpleDateFormat dateFormat,Date date){
    this.dateFormat = dateFormat;
    this.date = date;
    }
    public void run() {
    for(;;){
    String strDate = dateFormat.format(date);
    if(!"2010-01-12".equals(strDate)){
    System.err.println("tomorrow="+strDate);
    System.exit(0);
    }
    }
    }
    }

    运行的结果如下:

    Mon Jan 11 11:30:36 CST 2010
    Tue Jan 12 11:30:36 CST 2010
    tomorrow=2010-01-11

    终于看到问题了,tomorrow=2010-01-11,错得很明显了。其实要避免这个问题方法很简单,不使用SimpleDateFormat,或者不使用成员变量/静态成员变量的SimpleDateFormat对象即可。

     今天解决了一个findbug的错误:

    Call to method of static java.text.DateFormat in com.pbn.oss.resource.template.input.ws.service.InputTemplateWSServiceImpl.formatDate(Date)

    As the JavaDoc states, DateFormats are inherently unsafe for multithreaded use. The detector has found a call to an instance of DateFormat that has been obtained via a static field. This looks suspicous.

    初始代码如下:

    1. private static final SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");  
    2. format.format(new Date());  
    1. 同一个format 多次调用会导致线性不安全,

    可以改为:

     

      1. private static final String COMMON_DATE = "dd/MM/yyyy";  
      2. SimpleDateFormat format = new SimpleDateFormat(COMMON_DATE);  
      3. format.format(new Date()); 

    参考资料

    【1】.《使用SimpleDateFormat必须注意的问题

  • 相关阅读:
    Element-UI中Upload上传文件前端缓存处理
    Puppeteer前端自动化测试实践
    javascript-高级用法
    什么是闭包?闭包的优缺点?
    浅谈网站性能之前端性能优化
    2019前端面试题汇总(主要为Vue)
    从官网学习Node.js FS模块方法速查
    这才是官方的tapable中文文档
    面试官问:JS的this指向
    开启梦幻般的webrtc之旅
  • 原文地址:https://www.cnblogs.com/clds/p/5623436.html
Copyright © 2011-2022 走看看