我们在项目中经常听大家说simpledateformat是线程不安全的。有的同学就会反问,我一直使用simpledateformat好好地,也从来没遇到过线程不安全的问题啊。对于这种杠精来说,直接选择忽视。然后我们用代码实际演示下java中使用simpledateformat为什么是线程不安全的。
1)首先我们创建一个DateUtils类
package com.test.simpledateformat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String formatDate(Date date) throws Exception {
return sdf.format(date);
}
public static Date parse(String strDate) throws Exception {
return sdf.parse(strDate);
}
}
2)新建一个DateTask类
package com.test.simpledateformat;
public class DateTask extends Thread{
boolean flag = true;
@Override
public void run() {
while (flag) {
try {
this.join(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
flag = false;
}
try {
String aa = this.getName() + ":" + DateUtils.parse("2022-07-27 15:18:20");
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
}
}
}
3)编写测试方法
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
new Thread(new DateTask()).start();
}
}
然后我们运行,即可看到对应的报错信息
java.lang.NumberFormatException: For input string: "7.7E1"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:589)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2082)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.test.simpledateformat.DateUtils.parse(DateUtils.java:14)
at com.test.simpledateformat.DateTask.run(DateTask.java:18)
at java.lang.Thread.run(Thread.java:750)
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2082)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.test.simpledateformat.DateUtils.parse(DateUtils.java:14)
at com.test.simpledateformat.DateTask.run(DateTask.java:18)
at java.lang.Thread.run(Thread.java:750)
可以看到对应的报错了。那么是怎么回事呢?
其实就是SimpleDateFormat 继承了 DateFormat,这个dateformat里面使用到了calendar对象。在进行format的时候,会进行重复进行calendar.setTime(date),到后面整个流程就是:
线程 1 调用 format 方法,改变了 calendar 这个字段。
线程 1 中断了。
线程 2 开始执行,它也改变了 calendar。
线程 2 中断了。
线程 1 回来了
线程一多,则会出现各种问题,时间不对,线程挂死等等。所以最后就线程不安全了。
那么如何解决呢?可以有如下方法:
1、需要的时候创建新实例 2、使用同步:同步 SimpleDateFormat 对象 3、使用 ThreadLocal 4、java8中使用DateTimeFormatter
还没有评论,来说两句吧...