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;
}
}