不仅在客户端, 在服务器端也会有类似问题, servlet是多线程的, 调用后台的service层也是多线程的,如果service层中静态的,或是单例的 成员变量有多线程安全问题,就像 SimpleDataFormat 一样就会出现 取得的日期错误。
---------------------------------
在 log-services 项目中 用多线程来从不同ip下载,解析日志会出现异常。
在使用SimpleDataFormat parse 时, 会出现 NumberFormatException: For input string: ""
原因是SimpleDataFormat 是非线程安全的, 而我代码中的CommonService类中将其作为成员变量使用, 看源代码中 SimpleDataFormat 是 DateFormat的子类, DateFormat中定义了一个 Calendar, 在SimpleDataFormat 中有set(...) get(...)方法, 线程不安全。
参考
[url]http://stackoverflow.com/questions/4021151/java-dateformat-is-not-threadsafe-what-does-this-leads-to[/url]
解决方法
1, 不使用SimpleDataFormat 的成员变量, 改成零时变量
2, 在所有用到SimpleDataFormat 的地方都加上synchronized
3, 使用ThreadLocal
推荐使用使用ThreadLocal
---------------------------------
在 log-services 项目中 用多线程来从不同ip下载,解析日志会出现异常。
在使用SimpleDataFormat parse 时, 会出现 NumberFormatException: For input string: ""
原因是SimpleDataFormat 是非线程安全的, 而我代码中的CommonService类中将其作为成员变量使用, 看源代码中 SimpleDataFormat 是 DateFormat的子类, DateFormat中定义了一个 Calendar, 在SimpleDataFormat 中有set(...) get(...)方法, 线程不安全。
参考
[url]http://stackoverflow.com/questions/4021151/java-dateformat-is-not-threadsafe-what-does-this-leads-to[/url]
DateFormat exposes a calendar field of type Calendar, and looking at the code of SimpleDateFormat, some methods call calendar.set(...) and others call calendar.get(...). This is clearly not thread-safe.
解决方法
1, 不使用SimpleDataFormat 的成员变量, 改成零时变量
2, 在所有用到SimpleDataFormat 的地方都加上synchronized
3, 使用ThreadLocal
推荐使用使用ThreadLocal
public class DateFormatTest {
private static final ThreadLocal<DateFormat> df
= new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
public Date convert(String source)
throws ParseException{
Date d = df.get().parse(source);
return d;
}
}