当前位置: 首页 > 图灵资讯 > 技术篇> 多线程避免使用SimpleDateFormat及替代方案

多线程避免使用SimpleDateFormat及替代方案

来源:图灵教育
时间:2023-07-02 17:10:54

先来看一个多线程下使用的例子,运行结果会出现异常:import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; public class SimpleDateFormateTest {     public static void main(String[] args) {        final DateFormat df = new SimpleDateFormat("yyyyMMdd,HHmmss");        ExecutorService ts = Executors.newFixedThreadPool(100);        for (;;) {            ts.execute(new Runnable() {                         @Override                public void run() {                    try {                      //生成随机数,格式化日期                      String format =  df.format(new Date(Math.abs(new Random().nextLong())));                      System.out.println(format);                    } catch (Exception e) {                        e.printStackTrace();                        System.exit(1);                    }                }            });        }    }    }SimpledateFormat用于并发环境,正常开放式如下:为了在多线程环境下使用Simpledateformat,有六种方法:Simpledateformat的例子是在需要格式化的地方建立的,SimpleDateFormat实例public用于存储局部变量 static  String formatDate(Date date)throws ParseException{  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  return sdf.format(date);}这种方法可能会在短时间内创建大量的SimpleDateFormat实例,例如,在excel表格中分析字符串日期。为了避免创建大量的Simpledateformat实例,通常会考虑将Simpledateformat实例设置为静态成员变量,共享Simpledateformat对象。为了避免创建大量的Simpledateformat实例,方法2经常考虑将Simpledateformat实例设置为静态成员变量,共享Simpledateformat对象。在这种情况下,必须添加Simpledateformat同步。private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static String formatDate(Date date)throws ParseException{  synchronized(sdf){    return sdf.format(date);  }  }这种方法的缺点也很明显,在高并发性环境下,分析会被阻塞。方法三 方法加同步锁synchronized,同时只有一个线程可以执行类中的某个方法。方法三 方法加同步锁synchronized,同时只有一个线程可以执行类中的某个方法。缺点:性能差,每次锁释放后都要等其他线程进入。方案四 使用第三方包。我试过cn.hutool和common-lang3提供的fastdateformat的最终结果实际上并不令人满意,因为这两个包都没有帮助我检查异常时间。例如,2018年7月32日也被认为是正确的时间格式。方法5(推荐)在高并发环境下有更好的体验,Threadlocal可用于限制SimpledateFormat只能在线程中共享,从而避免了多线程造成的线程安全问题。 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {    @Override    protected DateFormat initialValue() {        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    }};public static String format(Date date) {    return threadLocal.get().format(date);}方案六 DatetimeFormater使用Java8提供新的日期时间API,它包括DateTimeFormatter,用于日期时间格式化,它与SimpleDateFormat有什么不同?两者最大的区别在于Java8的DatetimeFormater也是线程安全的,而SimpledateFormat则不是线程安全的。Stringg分析日期 dateStr= "2016年10月25日"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern(“yyyyy年MM月dd日”;   LocalDate date= LocalDate.parse(dateStr, formatter); 日期转换为字符串LocalDatetime now = LocalDateTime.now();  DateTimeFormatter format = DateTimeFormatter.ofPattern(”yyyy年MM月dd日 hh:mm a"); String nowStr = now .format(format);日期格式由DateTimeFormatter的静态方法ofPattern()构建,一些表示日期或时间的类别,如Localdatetime和Localdate,使用parse和format转换日期和字符串。使用新的API,整个转换过程都不需要考虑线程安全。