Java SImpleDateFormat线程安全问题
PHP中文网
PHP中文网 2017-04-17 17:31:32
0
3
498
public class Test {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private static class Task implements Runnable {

        public void run() {
            try {
                System.out.println(sdf.parse("2016-03-21 12:00:00").getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Task task = new Task();

        Thread t1 = new Thread(task);
        t1.start();
        Thread t2 = new Thread(task);
        t2.start();
        Thread t3 = new Thread(task);
        t3.start();
        Thread t4 = new Thread(task);
        t4.start();
        Thread t5 = new Thread(task);
        t5.start();
    }
}

最近才知道,如果像上面代码那样通过定义静态共享的实例来使用SimpleDateFormat是会存在线程安全问题的。

例如线程被挂死:

或者转换的时间不对:

然后自己尝试读JDK源码来试图分析在SimpleDateFormat的代码中,究竟是哪里的函数或者代码会引起线程不安全,但是由于水平有限,最后还是找不出。

哪位大牛可以帮忙分析一下。

PS:我的jdk版本:1.8.0_73

PHP中文网
PHP中文网

认证高级PHP讲师

全部回覆(3)
左手右手慢动作

我看了一下parse()原始碼的註釋,有一段是這位的

This parsing operation uses the {@link DateFormat#calendar

  • calendar} to produce a {@code Date}. All of the {@code

  • calendar}'s date-time fields are {@linkplain Calendar#clear()

  • cleared} before parsing, and the {@code calendar}'s default

  • values of the date-time fields are used for any missing

  • date-time information.

大概意思就是parse()方法使用calendar來產生傳回的Date實例,問題是這裡它用到的calendar不是每次方法執行時都新產生一個,它是定義了一個"protected Calendar calendar"屬性,按註解的意思,每次parse之前,都會把calendar裡的相關屬性都清除,然後用新的處理結果填充此對象,這樣的話在多線程裡邊,parse()執行過程中,就會出現一個線程剛把calendar設定好之後,另一個執行緒把它給清空了,因為都是一個sdf實例,其他問題原因應該都是這個

Ty80
private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

        boolean useDateFormatSymbols = useDateFormatSymbols();
        
        ...
 }  

這裡使用的calendar是類別成員,多執行緒去setTime會有執行緒安全問題

伊谢尔伦

這跟SimpleDateFormat的實作無關,與你多執行緒使用同一個物件有關,沒有做好執行緒同步

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板