疑问

来源:4-4 不佳做法

潇歌

2022-10-25

示例代码

public class ThreadLocal2 {

    public static ExecutorService threadPool = Executors.newFixedThreadPool(10);
    public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");


    public static void main(String[] args) {

        for (int i = 0; i < 1000; i++) {

            int finalI = i;
            threadPool.submit(() -> System.out.println(finalI + "---" + new ThreadLocal2().sec2Date(finalI)));

        }

    }

    private String sec2Date(int seconds) {
        Date date = new Date(seconds * 1000L);
        String format;
        synchronized (this) {
            format = dateFormat.format(date);
        }
        return format;
    }

}

悟空老师,你好,我这边自己测试了下,有两个问题,有时间辛苦解答下
第一个问题:没做线程同步相关的操作时,输出重复的日期值,是因为 SimpleDateFormat 本身线程不安全导致的吗,并非这里的 i++ 不是原子操作导致的是吗?因为我输出了不同的 finalI 是会对应相同的日期。
第二个问题:为什么我在 sec2Date 方法上加上 synchronized 和方法内部加上 synchronized(this) 依然会出现重复的值,而 synchronized(ThreadLocal2.class) 就不会输出相同的值。
如下图
图片描述
-----------------------------------------------分割线-----------------------------------------------
图片描述

写回答

1回答

悟空

2022-10-26

1、是因为 SimpleDateFormat 本身线程不安全导致的,并非i++,这里的i++没有多个线程一起执行,是线程安全的。

2、因为synchronized(ThreadLocal2.class) 意味着这个方法串行执行了,而另外的方式不能保证,因为每次是new ThreadLocal2()是新对象,可以看下synchronized的用法,就懂了。

0
5
潇歌
回复
悟空
好的,谢谢老师
2022-10-29
共5条回复

深度解密Java并发工具,精通JUC,成为并发多面手

JUC全方位讲解,构建并发工具类知识体系

1599 学习 · 573 问题

查看课程