| 方案 | 代碼 | 優點 | 缺點 |
| 1. 方法局部變量 | new SimpleDateFormat(pattern).format(date) | 簡單、無共享 | 高頻調用創建對象開銷大 |
| 2. ThreadLocal | ThreadLocal.withInitial(() -> new SimpleDateFormat(pattern)) | 線程隔離、復用實例 | 需手動管理生命周期,內存洩漏風險 |
| 3. 同步鎖 | synchronized(sdf) { sdf.format(date); } | 無新對象 | 高併發性能差,易死鎖 |
| 4. DateTimeFormatter (Java 8+) | DateTimeFormatter.ofPattern(pattern).format(localDateTime) | **線程安全、不可變、性能優、API 現代** | 需遷移至 java.time 類型 |
五、推薦:ThreadLocal 單例模式 (Java 7 環境必備)
public class DateFormatUtils {
private static final ThreadLocal SDF_THREAD_LOCAL =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static String format(Date date) {
return SDF_THREAD_LOCAL.get().format(date);
}
public static Date parse(String str) throws ParseException {
return SDF_THREAD_LOCAL.get().parse(str);
}
// 應用關閉時清理(可選)
public static void clear() { SDF_THREAD_LOCAL.remove(); }
}
六、現代遷移:DateTimeFormatter (Java 8+)
import java.time.*;
import java.time.format.DateTimeFormatter;
public class ModernDateFormat {
private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static String format(LocalDateTime ldt) { return FMT.format(ldt); }
public static LocalDateTime parse(String str) { return LocalDateTime.parse(str, FMT); }
// 舊 Date 互轉
public static String format(Date date) {
return FMT.format(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
}
public static Date parseToDate(String str) {
return Date.from(LocalDateTime.parse(str, FMT)
.atZone(ZoneId.systemDefault()).toInstant());
}
}
七、工具類封裝建議
public class DateUtils {
// 線程安全格式化器緩存
private static final Map FMT_CACHE = new ConcurrentHashMap<>();
public static DateTimeFormatter getFormatter(String pattern) {
return FMT_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
}
public static String format(LocalDateTime ldt, String pattern) {
return getFormatter(pattern).format(ldt);
}
public static LocalDateTime parse(String str, String pattern) {
return LocalDateTime.parse(str, getFormatter(pattern));
}
// Date 互轉略
}
八、總結建議
- **新項目強制使用
java.time + DateTimeFormatter**,從源頭杜絕線程安全問題
- 存量代碼若無法全量遷移,統一接入
ThreadLocal 工具類
- 禁用
static SimpleDateFormat 共享實例,Code Review 必檢項
- 格式化模式常量化,避免魔法字符串散落
掌握 SimpleDateFormat 線程安全本質與現代替代方案,是 Java 開發者進階的必修課。
- 上一篇文章: Java程序自動重啟實現方案:定時重啟與異常自愈
- 下一篇文章: Java按字節截取字符串並保證中文字符不拆分實現
Copyright ©
程式碼之家 All Rights Reserved