首页 > 编程语言 > 详细

ThreadLocal解决SimpleDateFormat多线程安全问题中遇到的困惑

时间:2018-02-22 12:49:37      阅读:265      评论:0      收藏:0      [点我收藏+]

 

测试代码:

public class Main {

    public static void main(String[] args) {

        for (int k = 0; k < 10; k++) {

            Runnable target = new Runnable() {

                @Override
                public void run() {
                    Object obj = dateFormatter.get();
                    System.out.println(Thread.currentThread().getName() + "  =>  " + obj);
                     obj = dateFormatter.get();
                }
            };
            new Thread(target, k+"").start();

        }

    }

    private static final ThreadLocal<SimpleDateFormat> dateFormatter = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
}

输出结果:

8 => java.text.SimpleDateFormat@f67a0200
5 => java.text.SimpleDateFormat@f67a0200
6 => java.text.SimpleDateFormat@f67a0200
...
7 => java.text.SimpleDateFormat@f67a0200

咦?怎么全是f67a0200一个实例?跟踪ThreadLocal代码寻找原因,百思不得其解。最后突然怀疑是SimpleDateFormat中toString方法的问题,SimpleDateFormat#toString源码如下:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

SimpleDateFormat#hashCode代码如下,其中pattern变量是SimpleDateFormat的格式字符串值( public SimpleDateFormat(String pattern))。

    @Override
    public int hashCode()
    {
        return pattern.hashCode();
        // just enough fields for a reasonable distribution
    }

 

所以如上原因可以得知,由于自己实现的initialValue方法的SimpleDateFormat的pattern都一样,所以不同sdf实例的toString最终输出相同。

     protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }

  

产生困惑原因:

  通常子类在没有重写toString方法时,我们都可以简单的根据toString值进行判断是否是一个实例,但是由于SimpleDateFormat自己实现了toString所以这个规则不在生效。

提醒:

  以后尽可能不要简单的将toString输出用来判断是否是一个实例,如果需要这么判断的话一定要检查toString方法。

 

拓展:

  在java.lang.ThreadLocal#getMap方法中可以发现原来java的Thread对线程局部变量自身就有支持,在Thread中有一个ThreadLocalMap的成员变量。java.lang.ThreadLocal#getMap源码如下:

    ThreadLocalMap getMap(Thread t) {
     //threadLocals是一个默认修饰符成员变量 return t.threadLocals; }

  

 

ThreadLocal解决SimpleDateFormat多线程安全问题中遇到的困惑

原文:https://www.cnblogs.com/leodaxin/p/8458127.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!