请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

ThreadLocalNormalUsage05,SimpleDateFormat如何做到的线程隔离?

在ThreadLocalNormalUsage05中,打印ThreadLocal和SimpleDateFormat对象,发现都是同一个对象,我的理解是线程池中的10个线程应该是创建了10个ThreadLocalMap,每个map中都存了一个Entry,key是同一个ThreadLocal对象的引用,value也都是同一个SimpleDateFormat对象,并没有看到副本的拷贝,但却保证了线程的隔离,这是如何做到的呢?

public class ThreadLocalNormalUsage05 {

    private static ExecutorService threadPool = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        for (int i = 0 ; i < 1000 ; i++) {
            int finalI = i;
            threadPool.submit(new Runnable() {
                public void run() {
                    String date = new ThreadLocalNormalUsage05().date(finalI);
                    System.out.println(date);
                }
            });
        }
        threadPool.shutdown();
    }

    private String date(int seconds) {
        //单位是毫秒
        Date date = new Date(seconds * 1000);
        SimpleDateFormat sdf = ThreadSafeDateFormatter.dateFormatThreadLocal.get();
        System.out.println(ThreadSafeDateFormatter.dateFormatThreadLocal);
        System.out.println(ThreadSafeDateFormatter.dateFormatThreadLocal.get());
        return sdf.format(date);
    }
}

class ThreadSafeDateFormatter {
    static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>(){
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal2 = ThreadLocal.withInitial(
            () -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
运行结果:
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
java.text.SimpleDateFormat@4f76f1a0
1970-01-01 08:00:07
1970-01-01 08:00:02
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
java.text.SimpleDateFormat@4f76f1a0
1970-01-01 08:00:08
1970-01-01 08:00:00
1970-01-01 08:00:01
1970-01-01 08:00:06
1970-01-01 08:00:04
1970-01-01 08:00:09

正在回答 回答被采纳积分+3

2回答

悟空 2020-01-02 23:49:52

示例代码:

    public String date(int seconds) {
        //参数的单位是毫秒,从1970.1.1 00:00:00 GMT计时
        Date date = new Date(1000 * seconds);
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal2.get();
        System.out.println(
                Thread.currentThread().getName() + ThreadSafeFormatter.dateFormatThreadLocal);
        SimpleDateFormat simpleDateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get();
        System.out.println(Thread.currentThread().getName() + simpleDateFormat.toString());
        System.out.println(
                Thread.currentThread().getName() + System.identityHashCode(simpleDateFormat));

        return dateFormat.format(date);
    }


0 回复 有任何疑惑可以回复我~
提问者 bfcpzk 2020-01-02 22:59:30

如果线程池中10个线程同时访问的还是同一个SimpleDateFormat对象,如何做到的线程安全呢?

0 回复 有任何疑惑可以回复我~
  • 悟空 #1
    你用这样的打印方式,看上去是同一个对象,但是并不是同一个对象,这样的打印是和hashCode有关的,不同的对象可以拥有相同的hashCode。
    你可以用System.identityHashCode(simpleDateFormat)来判断是否是同一个对象。
    
    
    参考:https://blog.csdn.net/qq_21963133/article/details/80624091
    回复 有任何疑惑可以回复我~ 2020-01-02 23:49:27
  • 提问者 bfcpzk 回复 悟空 #2
    明白啦,谢谢老师!
    回复 有任何疑惑可以回复我~ 2020-01-03 17:23:44
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信