文档章节

Call to static DateFormat

穿林度水
 穿林度水
发布于 2016/11/07 14:28
字数 756
阅读 12
收藏 0

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必须注意的问题

© 著作权归作者所有

穿林度水
粉丝 0
博文 250
码字总数 167120
作品 0
海淀
程序员
私信 提问
java常用时间函数

下面是我在项目开发里常用处理时间的函数 package analy; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; impo......

技术小胖子
2017/11/10
0
0
关于java中DateFormat类测试的总结

关于java中DateFormat类测试的总结 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Dat......

wanghuiwei888的博客
2017/12/21
0
0
日期操作类(DateFormat与SimpleDateFormat)的区别和实例

1.DateFormat类 此类是一个日期的格式化类,专门格式化日期的操作,因为java.util.Date类本身就已经包含了完整的日期,所以只需要将些日期按照一些好的格式格式化一下显示就好了. 观察DateForma...

xiahuawuyu
2012/06/15
14.2K
0
Java入门教程五(数字和日期处理)

  Java 提供了处理相关问题的类,包括 Math 类、Random 类、BigInteger 类、Date 类等。      Math类      Math 类封装了常用的数学运算,提供了基本的数学操作,如指数、对数、平...

SEOwhywhy
06/05
17
0
DateFormat 的多线程问题

DateFormat不是线程安全的,在jdk中是这么写的: SynchronizationDate formats are not synchronized. It is recommended to create separate format instances for each thread. If multip......

rain
2012/11/14
135
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
5
0
CSS盒子模型

CSS盒子模型 组成: content --> padding --> border --> margin 像现实生活中的快递: 物品 --> 填充物 --> 包装盒 --> 盒子与盒子之间的间距 content :width、height组成的 内容区域 padd......

studywin
今天
7
0
修复Win10下开始菜单、设置等系统软件无法打开的问题

因为各种各样的原因导致系统文件丢失、损坏、被修改,而造成win10的开始菜单、设置等系统软件无法打开的情况,可以尝试如下方法解决 此方法只在部分情况下有效,但值得一试 用Windows键+R打开...

locbytes
昨天
8
0
jquery 添加和删除节点

本文转载于:专业的前端网站➺jquery 添加和删除节点 // 增加一个三和一节点function addPanel() { // var newPanel = $('.my-panel').clone(true) var newPanel = $(".triple-panel-con......

前端老手
昨天
8
0
一、Django基础

一、web框架分类和wsgiref模块使用介绍 web框架的本质 socket服务端 与 浏览器的通信 socket服务端功能划分: 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn... 根据用户访问...

ZeroBit
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部