2024-03-23  阅读(3)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/2123216993

回答

SimpleDateFormat 不是线程安全,当多个线程使用一个 SimpleDateFormat 实例(如static修饰),调用 format() 格式化时,会出现线程不安全的情况。

其原因是 SimpleDateFormat 内部使用一个 Calendar 实例来存储解析和格式化的中间结果,但这个 Calendar 实例是一个成员变量且可变,当多个线程共享 SimpleDateFormat 时,也会共享 Calendar,然而 SimpleDateFormat 内部没有进行任何形式的锁或者同步机制来保护这个 Calendar,所以,在多线程环境下,他们之间就会互相干扰,导致日期解析或格式化错误。

详细分析

SimpleDateFormat 线程不安全演示

  • 示例一
    @Test
    public void test01() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        while (true){
            new Thread(() -> {
                String dateString = simpleDateFormat.format(new Date());
                try {
                    Date parseDate = simpleDateFormat.parse(dateString);
                    String dateString2 = simpleDateFormat.format(parseDate);
                    System.out.println(dateString.equals(dateString2));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

如果是线程安全的,那么结果输出一定全是 true,然后事实结果如下:

有报错的,有为 false,所以肯定不是线程安全的。

  • 示例二
    @Test
    public void test02() throws InterruptedException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str1 = "2024-01-25 11:12:13";
        String str2 = "2024-01-26 22:23:24";

        while (true) {
            new Thread(() -> {
                try {
                    System.out.println(str1 + ":" + simpleDateFormat.parse(str1));
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }).start();

            new Thread(() -> {
                try {
                    System.out.println(str2 + ":" + simpleDateFormat.parse(str2));
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }
    }

理论上来说,输出的结果应该是成对的: