SimpleDateFormat简介及替代方案
简介
SimpleDateFormat是一个时间格式化工具,可以将字符串格式化时间Date类型,也可以将Date类型格式化为字符串String类型,但其线程不安全。
常用方法
public final String format(Date date):
将时间格式化为我们想要的字符串。
public Date parse(String source):
将字符串格式化为Date类型。
代码
- format方法
static SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static ArrayList<Date> list=new ArrayList<>();
static {
// 每个线程对应处理的Date对象
// 我将会开启10个线程
Date date1 = new Date(2011-1900, Calendar.JANUARY,1);
Date date2 = new Date(2012-1900, Calendar.JANUARY,1);
Date date3 = new Date(2013-1900, Calendar.JANUARY,1);
Date date4 = new Date(2014-1900, Calendar.JANUARY,1);
Date date5 = new Date(2015-1900, Calendar.JANUARY,1);
Date date6 = new Date(2016-1900, Calendar.JANUARY,1);
Date date7 = new Date(2017-1900, Calendar.JANUARY,1);
Date date8 = new Date(2018-1900, Calendar.JANUARY,1);
Date date9 = new Date(2019-1900, Calendar.JANUARY,1);
Date date10 = new Date(2020-1900, Calendar.JANUARY,1);
list.add(date1);
list.add(date2);
list.add(date3);
list.add(date4);
list.add(date5);
list.add(date6);
list.add(date7);
list.add(date8);
list.add(date9);
list.add(date10);
}
/**
* 线程不安全
* 线程执行前和执行后,数据不一致
*
*
**/
public void formatdemo(){
ExecutorService service= Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int t = i;
service.execute(()->{
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Date date = list.get(t);
String format = SimpleDateFormatDemo.format.format(date);
System.out.println("线程"+Thread.currentThread().getName()+" 执行前: "+date);
System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+format);
});
}
}
- 执行结果
线程3执行前 和 执行后结果不一致,说明线程不安全
- parse方法
public void parsedemo(){
ExecutorService service= Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int t = i;
service.execute(()->{
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+format.parse("2021-12-12 12:23:23"));
} catch (ParseException e) {
e.printStackTrace();
}
});
}
}
- 执行结果
出现异常: Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: multiple points
线程不安全
解决办法
使用ThreadLocal
代码
public static final ThreadLocal<DateFormat> df=new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
static ArrayList<Date> list=new ArrayList<>();
static {
// 每个线程对应处理的Date对象
// 我将会开启10个线程
Date date1 = new Date(2011-1900, Calendar.JANUARY,1);
Date date2 = new Date(2012-1900, Calendar.JANUARY,1);
Date date3 = new Date(2013-1900, Calendar.JANUARY,1);
Date date4 = new Date(2014-1900, Calendar.JANUARY,1);
Date date5 = new Date(2015-1900, Calendar.JANUARY,1);
Date date6 = new Date(2016-1900, Calendar.JANUARY,1);
Date date7 = new Date(2017-1900, Calendar.JANUARY,1);
Date date8 = new Date(2018-1900, Calendar.JANUARY,1);
Date date9 = new Date(2019-1900, Calendar.JANUARY,1);
Date date10 = new Date(2020-1900, Calendar.JANUARY,1);
list.add(date1);
list.add(date2);
list.add(date3);
list.add(date4);
list.add(date5);
list.add(date6);
list.add(date7);
list.add(date8);
list.add(date9);
list.add(date10);
}
/**
* 线程不安全
* 线程执行前和执行后,数据不一致
*
*
**/
public void formatdemo(){
ExecutorService service= Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int t = i;
service.execute(()->{
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Date date = list.get(t);
System.out.println("线程"+Thread.currentThread().getName()+" 执行前: "+date);
System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+ df.get().format(date));
});
}
}
/**
* Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: multiple points
* 线程不安全
**/
public void parsedemo(){
ExecutorService service= Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int t = i;
service.execute(()->{
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+df.get().parse("2021-12-12 12:23:23"));
} catch (ParseException e) {
e.printStackTrace();
}
});
}
}
Gitee地址
XFS