LocalDateTime和Date的比较和区别 - 日常bb
LocalDateTime和Date的比较和区别

LocalDateTime和Date的比较和区别

LocalDate、LocalTime、LocalDateTime 都是 JDK1.8 新增的,为什么有了 Date 还要这几个呢?

在代码中我们直接使用 new Date() 直接输出,如果不格式化,结果如下
Tue Nov 03 11:01:22 CST 2020

可读性不行,如果要格式化就必须使用 SimpleDateFormat ,但是 SimpleDateFormat 时线程不安全的。

直接看看源码吧,calendar 是共享变量,并且没有对它做线程安全控制。
当多个线程同时使用相同的 SimpleDateFormat 对象(静态对象)调用 format 方法时,多个线程会同时调用 calendar.setTime(),可能一个线程刚设置好 time 值,另一个线程马上就把设置的 time 给修改了,导致得不到预期的结果。

// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo,
                            FieldDelegate delegate) {
    // Convert input date to time field list
    calendar.setTime(date);

    boolean useDateFormatSymbols = useDateFormatSymbols();

    for (int i = 0; i < compiledPattern.length; ) {
        int tag = compiledPattern[i] >>> 8;
        int count = compiledPattern[i++] & 0xff;
        if (count == 255) {
            count = compiledPattern[i++] << 16;
            count |= compiledPattern[i++];
        }

        switch (tag) {
        case TAG_QUOTE_ASCII_CHAR:
            toAppendTo.append((char)count);
            break;

        case TAG_QUOTE_CHARS:
            toAppendTo.append(compiledPattern, i, count);
            i += count;
            break;

        default:
            subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
            break;
        }
    }
    return toAppendTo;
}

SimpleDateFormat 除了 format 是线程不安全以外,parse 方法也是线程不安全的。
parse 方法实际取用 calb.establish(calendar).getTime() 的时间来解析。
calb.establish(calendar) 里主要完成了:

  1. 重置日期对象 cal 的属性值;
  2. 使用 calb 中的属性设置 cal;
  3. 返回设置好的 cal 对象;

但这三步操作并不是原子操作,所以也是线程不安全的。

多线程并发如何保证线程安全?

  1. 避免线程之间共享一个 SimpleDateFormat 对象,每个线程使用时都创建一个 SimpleDateFormat 对象(创建和销毁对象的开销大
  2. 对使用 format 和 parse 方法的地方进行加锁(线程阻塞性能差
  3. 使用 ThreadLocal 保证每个线程最多只创建一次 SimpleDateFormat (较好的方法

Date 对时间处理比较麻烦

想获取某年、某月、某星期,还有时间偏移等,处理起来太麻烦。
并且 getYear()、getMonth() 等方法都被弃用了。

使用 JDK1.8 全新的日期和时间 API

LocalDate,日期,构造指定的年月日

System.out.println(LocalDate.now());
// 结果:2020-11-03
System.out.println(LocalDate.of(2019, 11, 11));
// 结果:2019-11-11

获取年、月、日、星期几

LocalDate localDate = LocalDate.now();
// 2020
System.out.println(localDate.getYear());
// 2020
System.out.println(localDate.get(ChronoField.YEAR));
// NOVEMBER
System.out.println(localDate.getMonth());
// 11
System.out.println(localDate.get(ChronoField.MONTH_OF_YEAR));
// 3
System.out.println(localDate.getDayOfMonth());
// 3
System.out.println(localDate.get(ChronoField.DAY_OF_MONTH));
// TUESDAY
System.out.println(localDate.getDayOfWeek());
// 2
System.out.println(localDate.get(ChronoField.DAY_OF_WEEK));

获取时分秒

LocalTime localTime = LocalTime.now();
// 11:53:50.510
System.out.println(localTime);
System.out.println(localTime.getHour());
System.out.println(localTime.get(ChronoField.HOUR_OF_DAY));
System.out.println(localTime.getMinute());
System.out.println(localTime.get(ChronoField.MINUTE_OF_HOUR));
System.out.println(localTime.getSecond());
System.out.println(localTime.get(ChronoField.MICRO_OF_SECOND));

LocalDateTime 获取年月时分秒,相当于 LocalDate + LocalTime

LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
LocalDateTime localDateTime3 = localDate.atTime(localTime);
LocalDateTime localDateTime4 = localTime.atDate(localDate);

和 SimpleDateFormat 相比,DateTimeFormatter 是线程安全的。

# Java 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×