SimpleDateFormat线程不安全验证实验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package cn.qiweiwei.concurrentdate;
import java.text.SimpleDateFormat; import java.util.Date;
public class ConcurrentDateTest {
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static String date1String = "2010-03-04";
public static void main(String[] args) {
for (int i = 0; i < 10; i++) { new Thread(new Runnable() {
@Override public void run() { try { Date date1 = simpleDateFormat.parse(date1String); System.out.println(Thread.currentThread().getName() + ":" +date1); } catch (Exception e) { System.out.println("Thread error"); } } }).start(); }
}
}
|
输出结果:
1 2 3 4 5 6 7 8 9 10
| Thread error Thread error Thread-1:Sat Mar 04 00:00:00 CST 2220 Thread-9:Thu Mar 04 00:00:00 CST 2010 Thread-6:Thu Mar 04 00:00:00 CST 2010 Thread-4:Thu Mar 04 00:00:00 CST 2010 Thread-3:Thu Mar 04 00:00:00 CST 2010 Thread-7:Thu Mar 04 00:00:00 CST 2010 Thread-8:Thu Mar 04 00:00:00 CST 2010 Thread-5:Thu Mar 04 00:00:00 CST 2010
|
日期要么是错的,要么发生了异常。
解决办法:
加锁:线程内:synchronized(simpleDateFormat) { ..do parse and format. }
定义线程局部变量:变量是同一个,但是每个线程使用同一个初始值,存取数据只在本线程内有效(内部通过一个Map(实际是内部类ThreadLocalMap)存取数据,存取数据只在同一线程有效)
1 2 3 4 5 6
| private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){ @Override protected DateFormat initialValue(){ return new SimpleDateFormat("yyyy-MM-dd"); } };
|
使用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| new Thread(new Runnable() {
@Override public void run() { try { Date date1 = df.get().parse(date1String); System.out.println(Thread.currentThread().getName() + ":" +date1);
} catch (Exception e) { System.out.println("Thread error"); } } }).start();
|
- jdk8推荐方法:
使用 Instant 代替 Date, LocalDateTime 代替 Calendar,
DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释: simple beautiful strong
immutable thread-safe。
变量转换如链接所示:
https://www.cnblogs.com/niceboat/p/7027394.html
https://blog.csdn.net/u013604031/article/details/49812941