時間處理

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);
}
相關文章
相關標籤/搜索