SimpleDateFormat 的线程安全性问题java
public class DateFormat { // 多线程下存在问题,同步锁可解决 private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static class Task implements Runnable { @Override public void run() { try { System.out.println(simpleDateFormat.parse("2019-06-01 01:01:02")); } catch (ParseException e) { e.printStackTrace(); } } } private static void threadTest() { ExecutorService executorService= Executors.newFixedThreadPool(3); Task task = new Task(); Thread t1 = new Thread(task); Thread t2 = new Thread(task); Thread t3 = new Thread(task); Thread t4 = new Thread(task); Thread t5 = new Thread(task); executorService.execute(t1); executorService.execute(t2); executorService.execute(t3); executorService.execute(t4); executorService.execute(t5); executorService.shutdown(); } public static void main(String[] args) { threadTest(); } }
SimpleDateFormat类内部有一个Calendar对象引用,用来储存这个SimpleDateFormat相关的日期信息,多线程下会共享这个Calendar引用,会致使出现幻读成员变量的现象安全
解决办法:多线程
一、将SimpleDateFormat定义成局部变量。ide
缺点:每调用一次方法就会建立一个SimpleDateFormat对象,方法结束又要做为垃圾回收。性能
二、方法加同步锁synchronized,在同一时刻,只有一个线程能够执行类中的某个方法。线程
缺点:性能较差,每次都要等待锁释放后其余线程才能进入。orm
三、使用第三方库joda-time,由第三方考虑线程不安全的问题。(能够使用)对象
四、使用ThreadLocal:每一个线程拥有本身的SimpleDateFormat对象。(推荐使用)blog
使用ThreadLocal方式,以下:get
private static final ThreadLocal<SimpleDateFormat> df = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd"); } }; private static class TaskLocal implements Runnable { @Override public void run() { try { System.out.println(df.get().parse("2019-06-01 01:01:02")); } catch (ParseException e) { e.printStackTrace(); } } }
JDK8的应用,能够使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter
public static void main(String[] args) { LocalDateTime arrivalDate = LocalDateTime.now(); DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String landing = arrivalDate.format(format); System.out.println(landing); }