常用的日期工具类
我们在开发中通常需要对日期进行格式化,就想到了写一个工具类,如下:
1 | package com.kangyonggan.demo.util; |
追求性能的日期工具类
追求性能的同学可能会说:每次都new一个SimpleDateFormat太浪费了,于是有了下面一版:
1 | package com.kangyonggan.demo.util; |
测试临界资源问题
这个工具类在大多数的时候都是ok的,但是在高并发的时候就不是那么好使了,看看测试代码:
1 | package com.kangyonggan.demo.util; |
输出信息如下:
1 | Exception in thread "Thread-0" Exception in thread "Thread-1" java.lang.NumberFormatException: For input string: "101.E1012E" |
从错误信息来看是字符串的格式有误,但我们的入参时没错的,于是我稍微修改代码:i < 1
,即只有一个线程,这时候是不会报错的。
报错显然是多线程中临界资源simpleDateFormat
引起的,说明parse
方法不是线程安全的。查看SimpleDateFormat源码可以看到
1 | Date parsedDate; |
其中calendar
是成员变量:
1 | protected Calendar calendar; |
也就是说在多线程并发时,这个临界资源是可能被多个线程同时使用的。
解决方案
1. 在每次调用的时候去new一个
虽然可能会占用一些内存(一般不是很明显,忽略不计),但比较安全。
2. 访问临界资源时,使用同步
1 | package com.kangyonggan.demo.util; |
但是,当调用太过频繁时,会有阻塞,对性能有一定的影响。
3. 使用ThreadLocal
1 | package com.kangyonggan.demo.util; |
使用ThreadLocal有些情况下并不能减少对象的创建(如果一个线程只调用一次DateUtil),但是有些时候还是有效果的(一个线程多次调用DateUtil)。