Java - 【强制】SimpleDateFormat 是线程不安全的类
5. 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。
——引用《阿里巴巴Java开发手册》
/**
* private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
* 不推荐使用该方式格式化时间
* 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
* 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
* private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
* @Override
* protected DateFormat initialValue() {
* return new SimpleDateFormat("yyyy-MM-dd");}};
* 说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,
* 官方给出的解释:simple beautiful strong immutable thread-safe。
*/
/** ☆线程安全,推荐使用☆ */
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
}
};
public static Date formatp(Date date) throws ParseException {
return threadLocal.get().parse(threadLocal.get().format(date));
}
/*public static String format(Date date) {
return threadLocal.get().format(date);
}
public static Date formatp(String str) throws ParseException {
return threadLocal.get().parse(str);
}*/
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
public static void main(String[] args) throws ParseException {
new Thread(){
@Override
public void run() {
while (true){
String s = null;
try {
//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
s = String.valueOf(formatp(new Date()).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Thread0:\t"+s);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
String s = null;
try {
//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
s = String.valueOf(formatp(new Date()).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Thread1:\t"+s);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
String s = null;
try {
//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
s = String.valueOf(formatp(new Date()).getTime());
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Thread2:\t"+s);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
有兴趣的朋友可以按照上面的代码运行一遍,看一看这两种格式化时间戳的区别:
s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
s = String.valueOf(formatp(new Date()).getTime());