类型: 质量问题
格式化对象是非线程安全的,java.text.Format中的parse()和format()方法包含一个可导致用户看到其他用户数据的race condition。
public class DateFormat extends Thread{
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private String name;
private String dateStr;
public DateFormat(String name, String dateStr) {
this.name = name;
this.dateStr = dateStr;
}
@Override
public void run() {
try {
Date date = sdf.parse(dateStr);
System.out.println("线程"+name+"运行日期:"+date);
} catch (ParseException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(new DateFormat("A", "2017-06-10"));
executorService.execute(new DateFormat("B", "2016-06-06"));
executorService.shutdown();
}
}
如上代码中输出会有两种情况,一种情况是报错,还有一种情况是两个线程输出一致。出现这种情况的原因是因为SimpleDateFormat类内部有一个Calendar对象引用,它用来储存和这个SimpleDateFormat相关的日期信息。这样就会导致一个问题,如果SimpleDateFormat是static的, 那么多个thread之间就会共享SimpleDateFormat, 同时也是共享Calendar引用。在高并发的情况下,容易出现幻读成员变量的现象。