LocalDateTime等新出的日期类全是final修饰的类,不能被继承,且对应的日期变量都是final修饰的,也就是不可变类。赋值一次后就不可变,不存在多线程数据问题。
simpleDateFormat.parse() simpleDateFormat.format() 注意calendar.setTime(date);,Calendar类是里面基本都是final修饰的,calendar是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat,一般会封装在工具类,复用】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。 在多并发情况下使用SimpleDateFormat需格外注意: SimpleDateFormat除了format方法是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了
平时封装工具时,封装个静态的SimpleDataFormat 里面这个变量时共享变量,多线程时会出现这样的场景: A先设置,B也来设置时间值,由于并发了,后面C也来设置值,导致A,B取的值可能时C设置的值
结尾送上个我个人封装java8新的时间工具类供大家使用
package cn.linkkids.refund.util; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Date; public class DateUtil0 { private DateUtil0() throws Exception { throw new Exception("时间工具禁止new"); } public static final String YYYYMMDDHHMMSSS = "yyyyMMddHHmmss"; public static final String YYYY_MM_DD_HH_DD_SS_TIME = "yyyy-MM-dd HH:mm:ss"; public static final String YYYYMMDDHHMMSSTIME = "yyyy/MM/dd HH:mm:ss"; public static final String YYYY_MM_DD = "yyyy-MM-dd"; public static final String YYYYMMDD = "yyyy/MM/dd"; public static final String YYYYMMDDDATE = "yyyyMMdd"; //根据时间格式化成指定格式日期yyyyMMddHHmmss的字符串 public static String LocalDateTime_TO_YYYYMMDDHHMMSSS(LocalDateTime localDateTime) { //时间传唤为指定格式字符串 return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSS)); } //根据时间格式化成指定格式日期yyyy-MM-dd HH:mm:ss的字符串 public static String LocalDateTime_TO_YYYY_MM_DD_HH_DD_SS_TIME(LocalDateTime localDateTime) { //时间传唤为指定格式字符串 return localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_DD_SS_TIME)); } //根据时间格式化成指定格式日期yyyy/MM/dd HH:mm:ss的字符串 public static String LocalDateTime_TO_YYYYMMDDHHMMSSTIME(LocalDateTime localDateTime) { return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSTIME)); } //根据时间格式化成指定格式日期yyyy-MM-dd的字符串 public static String LocalDateTime_TO_YYYY_MM_DD(LocalDateTime localDateTime) { return localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD)); } //根据时间格式化成指定格式日期yyyy/MM/dd的字符串 public static String getYYYYMMDD01(LocalDateTime localDateTime) { return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDD)); } //根据时间格式化成指定格式日期yyyyMMdd的字符串 public static String LocalDateTime_TO_YYYYMMDDDATE(LocalDateTime localDateTime) { return localDateTime.format(DateTimeFormatter.ofPattern(YYYYMMDDDATE)); } /** * 以上是日期转换为指定格式字符串 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * */ //yyyy-MM-dd HH:mm:ss格式字符串 转化为时间 public static LocalDateTime YYYY_MM_DD_HH_DD_SS_TIME_TO_LocalDateTime(String dateStr) { return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_DD_SS_TIME)); } //YYYYMMDDHHMMSSS格式字符串 转化为时间 public static LocalDateTime YYYYMMDDHHMMSSS_TO_LocalDateTime(String dateStr) { return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSS)); } //yyyy/MM/dd HH:mm:ss 格式字符串 转化为时间 public static LocalDateTime YYYYMMDDHHMMSSTIME_TO_LocalDateTime(String dateStr) { return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDHHMMSSTIME)); } //yyyy-MM-dd 格式字符串 转化为时间 public static LocalDate COVERT_TO_YYYY_MM_DD_OF_LocalDateTime(String dateStr) { return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYY_MM_DD)); } //yyyy/MM/dd 格式字符串 转化为时间 public static LocalDate COVERT_TO_YYYYMMDD_TO_LocalDateTime(String dateStr) { return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDD)); } //yyyyMMdd 格式字符串 转化为时间 public static LocalDate COVERT_TO_YYYYMMDDDATE_OF_LocalDateTime(String dateStr) { return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(YYYYMMDDDATE)); } /** * 以上是指定格式字符串换为相应日期 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * */ //毫秒计时间戳 public static Long covertLocalDateTimeToSecondsMillions(LocalDateTime localDateTime) { return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli(); } //秒计时间戳 public static Long covertLocalDateTimeToSeconds(LocalDateTime localDateTime) { return localDateTime.toEpochSecond(ZoneOffset.of("+8")); } /** * 以上是日期转化为时间戳 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * */ //秒级时间戳转化为LocalDateTime // 入参是这种 时间戳 long second = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).getEpochSecond(); public static LocalDateTime covertMillisecondsToLocalDateTimeWithZone0(Long seconds) { //当前市区时间 LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.ofHours(8)); return localDateTime; } //秒级时间戳转化为LocalDateTime // 入参是这种 时间戳 long milliseconds = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); public static LocalDateTime covertMillisecondsToLocalDateTimeWithZone(Long milliseconds) { LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(milliseconds/1000, 0, ZoneOffset.ofHours(8)); return localDateTime; } //精确毫秒级别 保留三位小数的那种 //入参 long milliseconds = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); public static LocalDateTime covertMillisecondsToLocalDateTime(Long milliseconds) { LocalDateTime localDateTime = Instant.ofEpochMilli(milliseconds).atZone(ZoneOffset.ofHours(8)).toLocalDateTime(); return localDateTime; } /** * 以上是时间戳转化为日期 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * */ //LocalDateTime 转化为 Date public static Date covertDateTimeTODateTime(LocalDateTime localDateTime){ // 获得 Instant Instant instant = Instant.ofEpochSecond(localDateTime.toEpochSecond(ZoneOffset.ofHours(8))); // 获得 Date Date date = Date.from(instant); return date; } //LocalDateTime 转化为 Date public static Date covertDateTimeTODateTime_1(LocalDateTime localDateTime){ // 获得 Instant Instant instant = localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant(); // 获得 Date Date date = Date.from(instant); return date; } //LocalDate 转化为 Date public static Date covertLocalDateTODate(LocalDate localDate){ // 获得 Instant Instant instant = localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant(); // 获得 Date Date date = Date.from(instant); return date; } // Date转化为 LocalDate public static LocalDate covertDateToLocalDate(Date date){ // 获得 LocalDate LocalDate localDate = date.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDate(); return localDate; } }