最近看到一篇文章提到了SimpleDateFormater这个类。说这个类在单线程程序中没问题,但是在多线程环境下会线程安全的问题。
出于兴趣对这个问题进行了查证。网上有很多关于这个问题的文章,也解析了其中的原因。主要原因是因为SimpleDateFormat转换日期是通过Calendar对象来操作的,SimpleDateFormat继承DateFormat类,DateFormat类中维护一个Calendar对象,当多个线程同时操作这个对象时就会出现问题。
那么解决的办法呢?。有以下几种
1.在使用SimpleDateFormater时候尽量不要共享,每次使用的时候都创建一个新的对象
2.使用ThreadLocal来包装一下formater对象
ThreadLocal<SimpleDateFormat> local = new ThreadLocal<>();
SimpleDateFormat sdf = local.get();
3.使用LocalDateTime这个类来进行日期转换和处理(推荐)
针对第三种方法,重点介绍一下这个类。
这个类诶是java8推出的一个日期处理的工具类,在Time包下。
主要有三个类LocalDate,LocalTime,LocalDateTime。第一个是针对年月日,第二个针对时分秒,第三个是年月日加时分秒
这里以LocalDateTime为例,列举一些方法
//获取当前时间
LocalDateTime ldt = LocalDateTime.now();
//给定年月日时分秒获取时间
LocalDateTime ldt2 = LocalDateTime.of(2019, 1, 1, 1, 1, 1);
//给定年月日时分秒毫秒获取时间
LocalDateTime ldt3 = LocalDateTime.of(2019, 1, 1, 1, 1, 1, 1);
//给时间字符串获取时间
LocalDateTime ldt4 = LocalDateTime.parse("2019-01-10T17:07:05");
//获取LocalDateTime对象当月的第一天
LocalDateTime firstDayOfThisMonth = ldt4.with(TemporalAdjusters.firstDayOfMonth());
//获取LocalDateTime对象当月的第二天
LocalDateTime secondDayOfThisMonth = ldt4.withDayOfMonth(2);
//获取LocalDateTime对象当月的最后一天
LocalDateTime lastDayOfThisMonth = ldt4.with(TemporalAdjusters.lastDayOfMonth());
//获取LocalDateTime对象的后一天
LocalDateTime newtDay = ldt4.plusDays(1);
//获取LocalDateTime对象的当月第一个周一
LocalDateTime firstMondayOfDay = ldt4.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
//获取LocalDateTime对象的年,月,日
int year = ldt4.getYear();
int month = ldt4.getMonthValue();
int day = ldt4.getDayOfMonth();
//前一天
LocalDate l2 = ld.minusDays(1);
//后一天
LocalDate l3 = ld.plusDays(1);
这些是一些经常用到的方法,还有很多方法没有列出,感兴趣的可以去查找一个官方api。