SimpleDateFormat 使用 public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat();全局变量的方式来创建,将会出现线程不安全,请在方法内部重新new,出现线程安全问题,很难排查,开始的时候时间不对感觉可能是线程安全问题,使用线程池测试了好多次也没发现,今天又重新测试发现了问题(测试方法问题)。
DateTimeFormatter 是线程安全的,可以配合 LocalDateTime 使用,计算时间增加或减少非常方便,代码量也少。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class T{
public List<String> getList(){
List<String> list = new ArrayList();
list.add("2020-04-06 10:11:08");
list.add("2020-04-07 11:12:09");
list.add("2020-04-08 12:13:10");
list.add("2020-04-09 13:14:11");
list.add("2020-04-10 14:15:23");
list.add("2020-04-03 15:10:03");
list.add("2020-04-01 01:06:53");
list.add("2020-12-05 09:21:23");
list.add("2020-04-04 07:36:18");
list.add("2020-04-11 21:45:13");
return list;
}
private int getNum(int num) {
return (int) (Math.random() * num) + 1;
}
//普通线程测试
public void TestThread(){
List<String> list = getList();
for(int i = 0 ; i < list.size() ; i++){
int finalI = i;
new Thread(() -> {
String sTime;
Calendar cal = Calendar.getInstance();
cal.setTime(StrUtil.stringToDate(list.get(finalI)));
cal.add(Calendar.HOUR_OF_DAY, -1);
sTime = StrUtil.getCurStringDate(cal.getTime(), StrUtil.PATTERN);
System.out.println("SDF原时间:" + list.get(finalI) + " -> 计算后:" + sTime);
LocalDateTime startTime = LocalDateTime.parse( list.get(finalI),StrUtil.dtf);
LocalDateTime newTime = startTime.plusHours(-1);
System.out.println("原时间:" + list.get(finalI) + " -> 计算后:" + newTime.format(StrUtil.dtf));
}).start();
}
}
//线程池测试
public void TestThreadPool(){
ExecutorService executor = Executors.newFixedThreadPool(10);
List<String> list = getList();
for(int i = 0 ; i < list.size() ; i++){
int finalI = i;
executor.submit(()->{
String sTime;
Calendar cal = Calendar.getInstance();
cal.setTime(StrUtil.stringToDate(list.get(finalI)));
cal.add(Calendar.HOUR_OF_DAY, -1);
sTime = StrUtil.getCurStringDate(cal.getTime(), StrUtil.PATTERN);
System.out.println("SDF原时间:" + list.get(finalI) + " -> 计算后:" + sTime);
LocalDateTime startTime = LocalDateTime.parse( list.get(finalI),StrUtil.dtf);
LocalDateTime newTime = startTime.plusHours(-1);
System.out.println("原时间:" + list.get(finalI) + " -> 计算后:" + newTime.format(StrUtil.dtf));
});
}
}
public static void main(String[] args) {
T t = new T();
t.TestThread();
t.TestThreadPool();
}
}
class StrUtil {
public static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//线程安全
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat();//线程不安全
public static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 获取指定时间的时间字符串,在多线程中此方法将不安全(如何必须要使用,请在方法内部new不要使用全局变量)
*/
public static String getCurStringDate(Date date, String pattern) {
DATE_FORMAT.applyPattern(pattern);
return DATE_FORMAT.format(date);
}
/**
* 字符串转日期对象
*/
public static Date stringToDate(String str) {
SimpleDateFormat format;
if (str.length() == 16) {
format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
} else if (str.length() == 10) {
format = new SimpleDateFormat("yyyy-MM-dd");
} else {
format = new SimpleDateFormat(StrUtil.PATTERN);
}
try {
return format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}