Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(二)

②. 从阿里ThreadLocal规范开始


  • ①. 公司业务:在对一些业务日志写入数据库的时候,日期调用了sdf的静态,导致了会报错或者日期乱了(生产故障)


Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(二)


①. 非线程安全的SimpleDateFormat


  • ①. 写时间工具类,一般写成静态的成员变量,不知,此种写法的多线程下的危险性!


  • ②. 代码展示


public class DateUtils
{
    public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 模拟并发环境下使用SimpleDateFormat的parse方法将字符串转换成Date对象
     * @param stringDate
     * @return
     * @throws Exception
     */
    public static Date parseDate(String stringDate)throws Exception
    {
        return sdf.parse(stringDate);
    }
    
    public static void main(String[] args) throws Exception
    {
        for (int i = 1; i <=30; i++) {
            new Thread(() -> {
                try {
                    System.out.println(DateUtils.parseDate("2020-11-11 11:11:11"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}


③. bug


Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(二)


④. 源码分析结论(了解)


SimpleDateFormat类内部有一个Calendar对象引用,它用来储存和这个


SimpleDateFormat相关的日期信息,例如sdf.parse(dateStr),sdf.format(date) 诸如此类的方法参数传入的日期相关String,Date等等, 都是交由Calendar引用来储存的.这样就会导致一个问题如果你的SimpleDateFormat是个static的, 那么多个thread 之间就会共享这个SimpleDateFormat, 同时也是共享这个Calendar引用


Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(二)


Juc17_ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法(二)


②. 将SimpleDateFormat定义成局部变量(方案一)


  • 缺点:每调用一次方法就会创建一个SimpleDateFormat对象,方法结束又要作为垃圾回收


public class DateUtils
{
    public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 模拟并发环境下使用SimpleDateFormat的parse方法将字符串转换成Date对象
     * @param stringDate
     * @return
     * @throws Exception
     */
    public static Date parseDate(String stringDate)throws Exception
    {
        return sdf.parse(stringDate);
    }

    public static void main(String[] args) throws Exception
    {
        for (int i = 1; i <=30; i++) {
            new Thread(() -> {
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    System.out.println(sdf.parse("2020-11-11 11:11:11"));
                    sdf = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }



上一篇:IOTE2016:透析物联网行业热点 把脉产业链发展趋势


下一篇:RSA总裁预测2016年网络安全趋势