转自:http://blog.csdn.net/jeamking/article/details/7183958

有时我们在同一个类中都是使用同一种日期格式,又或者为了减少new SimpleDateFormat次数,自然而然的就会出现如下代码:

private static SimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");

但是这样做在多线程并发下会存在安全隐患。SimpleDateFormat 类并不是线程同步的,JDK中我们可以看到如下描述:

* Date formats are not synchronized.

* Itis recommended to create separate format instances for each thread.

* Ifmultiple threads access a format concurrently, it must be synchronized

*externally.

下面通过一个简单程序来进行测试:

public class DateUtil {

privatestatic SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss");

publicDate parse(String str) throws ParseException{

returnsdf.parse(str);

}

}

public class Test {

/**

* @param args

* @throws InterruptedException

*/

publicstatic void main(String[] args) throws InterruptedException {

SdfRunnablett = new SdfRunnable();

for(inti=0;i<10;i++){

newThread(tt).start();

}

}

}

输出结果:

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Exception in thread "Thread-1"java.lang.NumberFormatException: multiple points

atsun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)

atjava.lang.Double.parseDouble(Unknown Source)

atjava.text.DigitList.getDouble(Unknown Source)

atjava.text.DecimalFormat.parse(Unknown Source)

atjava.text.SimpleDateFormat.subParse(Unknown Source)

atjava.text.SimpleDateFormat.parse(Unknown Source)

atjava.text.DateFormat.parse(Unknown Source)

atDateUtil.parse(DateUtil.java:8)

atSdfRunnable.run(SdfRunnable.java:8)

atjava.lang.Thread.run(Unknown Source)

多运行几次,并不每次都输出这个错误信息,还可能输出如下错误信息:

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Wed Sep 23 12:23:35 CST 2201

Fri Dec 23 12:23:35 CST 2011

Exception in thread "Thread-6"java.lang.NumberFormatException: empty String

atsun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)

atjava.lang.Double.parseDouble(Unknown Source)

atjava.text.DigitList.getDouble(Unknown Source)

atjava.text.DecimalFormat.parse(Unknown Source)

atjava.text.SimpleDateFormat.subParse(Unknown Source)

atjava.text.SimpleDateFormat.parse(Unknown Source)

atjava.text.DateFormat.parse(Unknown Source)

atDateUtil.parse(DateUtil.java:8)

atSdfRunnable.run(SdfRunnable.java:8)

atjava.lang.Thread.run(Unknown Source)

Exception in thread "Thread-1"java.lang.NumberFormatException: For input string: ""

atjava.lang.NumberFormatException.forInputString(Unknown Source)

atjava.lang.Long.parseLong(Unknown Source)

atjava.lang.Long.parseLong(Unknown Source)

atjava.text.DigitList.getLong(Unknown Source)

atjava.text.DecimalFormat.parse(Unknown Source)

atjava.text.SimpleDateFormat.subParse(Unknown Source)

atjava.text.SimpleDateFormat.parse(Unknown Source)Fri Dec 23 12:23:35 CST 2011

atjava.text.DateFormat.parse(Unknown Source)

atDateUtil.parse(DateUtil.java:8)

atSdfRunnable.run(SdfRunnable.java:8)

atjava.lang.Thread.run(Unknown Source)

在以上示例中我们把SimpleDateFormat定义为静态成员的。接下来我们把SimpleDateFormat定义为类普通成员。

public class DateUtil {

privateSimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

publicDate parse(String str) throws ParseException{

returnsdf.parse(str);

}

}

再次运行程序,结果如下:

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

Fri Dec 23 12:23:35 CST 2011

程序运行正常。并没有出现错误信息。那么,是不是意味着SimpleDateFormat作为普通成员就没有安全隐患呢,请看如下示例:

public class SdfRunnable implementsRunnable {

privateSimpleDateFormat sdf;

privateString dateStr;

publicSdfRunnable(SimpleDateFormat sdf,String dateStr){

this.sdf= sdf;

this.dateStr= dateStr;

}

publicvoid run() {

try{

System.out.println(this.sdf.parseObject(this.dateStr));

}catch (ParseException e) {

e.printStackTrace();

}

}

}

public class Test {

/**

* @param args

* @throws InterruptedException

*/

publicstatic void main(String[] args) throws InterruptedException {

SimpleDateFormatsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

SdfRunnablett = new SdfRunnable(sdf,"2011-12-34 12:23:11");

for(inti=0;i<10;i++){

newThread(tt).start();

}

}

}

运行输出结果如下:

Tue Jan 03 12:23:11 CST 2012

Tue Jan 03 12:23:11 CST 2012

Tue Jan 03 12:23:11 CST 2012

Tue Jan 03 12:23:11 CST 2012

Tue Jan 03 12:23:11 CST 2012

Thu Jan 01 00:00:11 CST 1970

Sun Jan 03 12:23:11 CST 1971

Tue Jan 03 12:23:11 CST 2012

Exception in thread "Thread-9"java.lang.NumberFormatException: multiple points

atsun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)

atjava.lang.Double.parseDouble(Unknown Source)

atjava.text.DigitList.getDouble(Unknown Source)

atjava.text.DecimalFormat.parse(Unknown Source)

atjava.text.SimpleDateFormat.subParse(Unknown Source)

atjava.text.SimpleDateFormat.parse(Unknown Source)

atjava.text.DateFormat.parseObject(Unknown Source)

atjava.text.Format.parseObject(Unknown Source)

atSdfRunnable.run(SdfRunnable.java:14)

atjava.lang.Thread.run(Unknown Source)

由此可见,不管是SimpleDateFormat作为静态成员还是成员,在多线程并发下都会存在安全隐患。所以应该在需要使用的地方再new SimpleDateFormat()。

关于SimpleDateFormat非多线程安全问题,在sun的bug database(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4228335)中有更多的描述。

SimpleDateFormat做成员或者静态成员多线程安全隐患的更多相关文章

  1. C++学习5-面向对象编程基础(构造函数、转换构造、静态数据成员、静态成员函数、友元)

    知识点学习 类 const作用 C语言的const限定符的含义为"一个不能改变值的变量",C++的const限定符的含义为"一个有类型描述的常量": const ...

  2. iOS - 互斥锁&&自旋锁 多线程安全隐患(转载)

    一.多线程安全隐患 资源共享  一块资源可能会被多个线程共享,也就是多个线程可能会访问到一块资源 比如多个线程访问同一个对象,同一个变量,同一个文件. 当多线程访问同一块资源的时候,很容易引发数据错乱 ...

  3. JS OOP -04 JS中的公有成员,私有成员和静态成员

    JS中的公有成员,私有成员和静态成员 a.实现类的公有成员 b.实现类的私有成员 c.实现类的静态成员 a.实现类的公有成员 之前定义的任何类型成员都属于公有成员的范畴,该类的任何实例都对外公开这些属 ...

  4. C++类中的常成员和静态成员

    常变量.常对象.常引用.指向常对象或常变量的指针等在定义时都使用了const关键字,这是C++语言引入的一种数据保护机制,称为const数据保护机制.例如通过const关键字主动地将被调函数形参进行限 ...

  5. 精读JavaScript模式(七),命名空间模式,私有成员与静态成员

    一.前言 惰性十足,这篇2月19号就开始写了,拖到了现在,就是不愿意花时间把看过的东西整理一下,其它的任何事都比写博客要有吸引力,我要反省自己. 从这篇开始,是关于JS对象创建模式的探讨,JS语言简单 ...

  6. C++ 静态数据成员和静态成员函数

    一 静态数据成员: 1.静态数据成员的定义. 静态数据成员实际上是类域中的全局变量.所以,静态数据成员的定义(初始化)不应该被放在头文件中,因为这样做会引起重复定义这样的错误.即使加上#ifndef ...

  7. js 独立命名空间,私有成员和静态成员

    独立的命名空间   1可以避免全局变量污染. 全局变量污染不是 说 被全局变量污染,而是说不会污染全局变量.   2实现私有成员. 在js中函数 就可以满足独立的命名空间的两点需求.   如:     ...

  8. C# 多线程程序隐患

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. C++基础(静态数据成员和静态成员函数)

    [简介] 1.静态数据成员在类中声明,在源文件中定义并初始化: 2.静态成员函数没有this指针,只能访问静态数据成员: 3.调用静态成员函数:(1)对象.(2)直接调用: 4.静态成员函数的地址可用 ...

随机推荐

  1. eclipse 执行out.request()方法提示out cannot be resolved

    添加代码:PrintWriter out = response.getWriter(); 支持中文:response.setContentType("text/html;charset=ut ...

  2. 黑马程序员——OC语言Foundation框架 NSArray NSSet NSDictionary\NSMutableDictionary

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一) NSNumber 将各种基本数据类型包装成NSNumber对象 @ ...

  3. JS日期的获取与加减

    1)获取当前日期: var today = new Date(); 2)设定某个日期: var d = new Date("2015/1/08".replace(/-/g,&quo ...

  4. The Layout Process on Mac OSX and iOS

    First we will recap the steps it takes to bring views on screen with Auto Layout enabled. When you’r ...

  5. 在线工具、setHtmlRem、px2rem

    http://tool.lu/c/developer  开发类在线工具 https://github.com/leon776/setHtmlRem   setHtmlRem https://githu ...

  6. JSP 数据库连接类 MySql数据库

    数据库连接类的主要功能是连接数据库并且获得连接对象,以及关闭数据库.通过创建该类的实例,调用其中的方法,以避免重复操作. package chapter13; import java.sql.*; p ...

  7. ubuntu15.10跑裸机程序跑.bin文件

    1:安装tftp:#apt-get update#apt-get install tftp-hpa tftpd-hpa xinetd2:#cd /srv#mkdir tftp#chmod 777 tf ...

  8. Java:String和Date、Timestamp之间的转换

    一.String与Date(java.util.Date)互转 1.1 String -> Date String dateStr = "2016-9-28 12:25:55" ...

  9. HDU 2274 Magic WisKey

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2274 Magic WisKey Time Limit: 2000/1000 MS (Java/Othe ...

  10. hbase-architecture

    https://www.mapr.com/blog/in-depth-look-hbase-architecture http://stackoverflow.com/questions/400679 ...