SimpleDateFormat
类SimpleDateFormat主要负责日期的转换以及格式化,多线程环境下多个线程同时操作一个SimpleDateFormat对象会造成数据转换不准确,是非线程安全的类。
单例模式下多线程不安全的示例:
public class SimpleDateFormatDemo {
public static class MyThread extends Thread{
SimpleDateFormat sdf;
String dateString;
//初始化
public MyThread(SimpleDateFormat sdf, String dateString) {
this.sdf = sdf;
this.dateString = dateString;
}
@Override
public void run() {
try {
Date date = sdf.parse(dateString);
String newDateString = sdf.format(date);
System.out.println("目标时间:" + dateString + "-----转换之后时间为:"+newDateString);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String[] dates = new String[]{"2020-01-02 12:22:33","2020-02-03 12:22:33","2020-03-04 12:22:33","2020-04-05 12:22:33","2020-05-06 12:22:33",
"2020-06-07 12:22:33","2020-07-08 12:22:33","2020-08-09 12:22:33","2020-09-10 12:22:33","2020-10-11 12:22:33"};
Thread[] threads = new Thread[10];
for (int i = 0; i<10; i++){
threads[i] = new MyThread(sdf,dates[i]);
}
for (Thread thread : threads){
thread.start();
}
}
目标时间:2020-02-03 12:22:33-----转换之后时间为:2020-02-03 12:22:33
目标时间:2020-04-05 12:22:33-----转换之后时间为:2020-04-05 12:22:33
目标时间:2020-08-09 12:22:33-----转换之后时间为:2020-08-09 12:22:33
目标时间:2020-06-07 12:22:33-----转换之后时间为:2020-06-07 12:22:33
目标时间:2020-10-11 12:22:33-----转换之后时间为:2020-01-11 12:22:33
目标时间:2020-07-08 12:22:33-----转换之后时间为:2020-07-08 12:22:33
目标时间:2020-03-04 12:22:33-----转换之后时间为:2020-01-11 12:22:33
目标时间:2020-01-02 12:22:33-----转换之后时间为:2020-01-02 12:22:33
目标时间:2020-05-06 12:22:33-----转换之后时间为:2020-05-06 12:22:33
目标时间:2020-09-10 12:22:33-----转换之后时间为:2020-09-10 12:22:33
创建多个SimpleDateFormat实例解决
public class SimpleDateFormatDemo {
public static class MyThread extends Thread{
String formatPattern;
String dateString;
//初始化
public MyThread(String formatPattern, String dateString) {
this.formatPattern = formatPattern;
this.dateString = dateString;
}
@Override
public void run() {
try {
//调用DateTools下方法
Date date = DateTools.parse(formatPattern,dateString);
String newDateString = DateTools.format(formatPattern,date);
System.out.println("目标时间:" + dateString + "-----转换之后时间为:"+newDateString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//DateTools类
public static class DateTools{
public static Date parse(String formatPattern,String dateString) throws Exception{
//每次调用parse方法都new一个SimpleDateFormat对象,就不存在多个线程同时操作一个SimpleDateFormat的情况
return new SimpleDateFormat(formatPattern).parse(dateString);
}
public static String format(String formatPattern,Date date){
return new SimpleDateFormat(formatPattern).format(date);
}
}
public static void main(String[] args) {
String formatPattern = "yyyy-MM-dd HH:mm:ss";
String[] dates = new String[]{"2020-01-02 12:22:33","2020-02-03 12:22:33","2020-03-04 12:22:33","2020-04-05 12:22:33","2020-05-06 12:22:33",
"2020-06-07 12:22:33","2020-07-08 12:22:33","2020-08-09 12:22:33","2020-09-10 12:22:33","2020-10-11 12:22:33"};
Thread[] threads = new Thread[10];
for (int i = 0; i<10; i++){
threads[i] = new MyThread(formatPattern,dates[i]);
}
for (Thread thread : threads){
thread.start();
}
}
}
目标时间:2020-05-06 12:22:33-----转换之后时间为:2020-05-06 12:22:33
目标时间:2020-09-10 12:22:33-----转换之后时间为:2020-09-10 12:22:33
目标时间:2020-03-04 12:22:33-----转换之后时间为:2020-03-04 12:22:33
目标时间:2020-01-02 12:22:33-----转换之后时间为:2020-01-02 12:22:33
目标时间:2020-02-03 12:22:33-----转换之后时间为:2020-02-03 12:22:33
目标时间:2020-07-08 12:22:33-----转换之后时间为:2020-07-08 12:22:33
目标时间:2020-08-09 12:22:33-----转换之后时间为:2020-08-09 12:22:33
目标时间:2020-06-07 12:22:33-----转换之后时间为:2020-06-07 12:22:33
目标时间:2020-04-05 12:22:33-----转换之后时间为:2020-04-05 12:22:33
目标时间:2020-10-11 12:22:33-----转换之后时间为:2020-10-11 12:22:33
创建多个SimpleDateFormat实例解决
public class SimpleDateFormatDemo {
public static class MyThread extends Thread {
String formatPattern;
String dateString;
//初始化
public MyThread (String formatPattern, String dateString) {
this.formatPattern = formatPattern;
this.dateString = dateString;
}
@Override
public void run() {
try {
//通过DateTools获取当前线程ThreadLocal中的SimpleDateFormat对象
SimpleDateFormat sdf = DateTools.getSimpleDateFormat(formatPattern);
Date date = sdf.parse(dateString);
String newDateString = sdf.format(date);
System.out.println("目标时间:" + dateString + "-----转换之后时间为:"+newDateString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class DateTools {
//用ThreadLocal存储SimpleDateFormat,多个线程之间互不干扰
private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
//初始化并返回ThreadLocal下SimpleDateFormat对象
public static SimpleDateFormat getSimpleDateFormat(String formatPattern){
SimpleDateFormat sdf = null;
sdf = threadLocal.get();
if(sdf == null){
sdf = new SimpleDateFormat(formatPattern);
threadLocal.set(sdf);
}
return threadLocal.get();
}
}
public static void main(String[] args) {
String formatPattern = "yyyy-MM-dd HH:mm:ss";
String[] dates = new String[]{"2020-01-02 12:22:33","2020-02-03 12:22:33","2020-03-04 12:22:33","2020-04-05 12:22:33","2020-05-06 12:22:33",
"2020-06-07 12:22:33","2020-07-08 12:22:33","2020-08-09 12:22:33","2020-09-10 12:22:33","2020-10-11 12:22:33"};
Thread[] threads = new Thread[10];
for (int i = 0; i<10; i++){
threads[i] = new MyThreadDemo(formatPattern,dates[i]);
}
for (Thread thread : threads){
thread.start();
}
}
}
目标时间:2020-09-10 12:22:33-----转换之后时间为:2020-09-10 12:22:33
目标时间:2020-05-06 12:22:33-----转换之后时间为:2020-05-06 12:22:33
目标时间:2020-03-04 12:22:33-----转换之后时间为:2020-03-04 12:22:33
目标时间:2020-04-05 12:22:33-----转换之后时间为:2020-04-05 12:22:33
目标时间:2020-10-11 12:22:33-----转换之后时间为:2020-10-11 12:22:33
目标时间:2020-02-03 12:22:33-----转换之后时间为:2020-02-03 12:22:33
目标时间:2020-08-09 12:22:33-----转换之后时间为:2020-08-09 12:22:33
目标时间:2020-06-07 12:22:33-----转换之后时间为:2020-06-07 12:22:33
目标时间:2020-07-08 12:22:33-----转换之后时间为:2020-07-08 12:22:33
目标时间:2020-01-02 12:22:33-----转换之后时间为:2020-01-02 12:22:33