ThreadLocal 解决 多线程有关问题

ThreadLocal 解决 多线程问题
不仅在客户端, 在服务器端也会有类似问题, servlet是多线程的, 调用后台的service层也是多线程的,如果service层中静态的,或是单例的 成员变量有多线程安全问题,就像 SimpleDataFormat 一样就会出现 取得的日期错误。


---------------------------------
在 log-services 项目中 用多线程来从不同ip下载,解析日志会出现异常。

在使用SimpleDataFormat parse 时, 会出现 NumberFormatException: For input string: ""

原因是SimpleDataFormat 是非线程安全的, 而我代码中的CommonService类中将其作为成员变量使用, 看源代码中 SimpleDataFormat 是 DateFormat的子类, DateFormat中定义了一个 Calendar, 在SimpleDataFormat 中有set(...) get(...)方法, 线程不安全。

参考
http://*.com/questions/4021151/java-dateformat-is-not-threadsafe-what-does-this-leads-to

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;
  }
}