2012-09-21 40 views
4

我想向同事展示SimpleDateFormat是而不是通過簡單的JUnit測試可確保線程安全。下面的類沒有使我的觀點(在多線程環境中重用SimpleDateFormat),我不明白爲什麼。你能發現什麼阻止了我使用SDF拋出運行時異常嗎?證明SimpleDateFormat不是線程安全的

public class SimpleDateFormatThreadTest 
{ 
    @Test 
    public void test_SimpleDateFormat_MultiThreaded() throws ParseException{ 
     Date aDate = (new SimpleDateFormat("dd/MM/yyyy").parse("31/12/1999")); 
     DataFormatter callable = new DataFormatter(aDate); 

     ExecutorService executor = Executors.newFixedThreadPool(1000); 
     Collection<DataFormatter> callables = Collections.nCopies(1000, callable); 

     try{ 
      List<Future<String>> futures = executor.invokeAll(callables); 
      for (Future f : futures){ 
       try{ 
        assertEquals("31/12/1999", (String) f.get()); 
       } 
       catch (ExecutionException e){ 
        e.printStackTrace(); 
       } 
      } 
     } 
     catch (InterruptedException e){ 
      e.printStackTrace(); 
     } 
    } 
} 

class DataFormatter implements Callable<String>{ 
    static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 

    Date date; 

    DataFormatter(Date date){ 
     this.date = date; 
    } 

    @Override 
    public String call() throws RuntimeException{ 
     try{ 
      return sdf.format(date); 
     } 
     catch (RuntimeException e){ 
      e.printStackTrace(); 
      return "EXCEPTION"; 
     } 
    } 
} 
+1

你應該告訴你的同事閱讀javadoc,以便繼續做一些適當的工作! –

+0

是的SimpleDateFormat不是線程安全的,我們(壞)的經驗是,它不會拋出異常,它執行瘋狂的格式(實際上更糟糕)。嘗試在代碼中輸出值。 –

+0

爲每個線程創建另一個SDF並對其進行格式化。然後比較輸出並在輸出不匹配時拋出異常。 – Stefan

回答

11

缺乏線程安全性並不一定意味着代碼將拋出異常。試試通過安迪格羅夫的文章:SimpleDateFormat and Thread Safety;他表明,在給定不同輸入的情況下,輸出不總是正確的,從而表現出缺乏線程安全性。

當我運行這段代碼,我得到以下輸出:

java.lang.RuntimeException: date conversion failed after 3 iterations. 
Expected 14-Feb-2001 but got 01-Dec-2007 

注意,「01日 - 12月2007」是不是即使在測試數據的一個字符串。它實際上是其他兩個線程正在處理的日期的組合!

+0

它可能會拋出異常,但它們會被僞裝成奇怪的解析異常,就像這裏所討論的異常一樣(http://www.coderanch.com/t/569795/java/java/SimpleDateFormat-not -Thread安全)。 – Brian

+0

我閱讀了文章並相應地更新了我的代碼。但仍然無法在我的JUnit上看到這種行爲。這是我誤解多線程的東西嗎? – Pomario

+0

@Pomario:也許嘗試給它不同的日期格式在同一時間? – Claudiu

4

這是不是來自javadoc of SimpleDateFormatter有足夠的證據呢?

同步

日期格式不同步。建議爲每個線程創建單獨的格式實例。如果多個線程同時訪問一個格式,它必須在外部同步。

而不是線程安全的主要觀察是獲得意想不到的結果,而不是例外。

3

這是不是因爲這個代碼在SimpleDateFormat線程安全(在太陽JVM 1.7.0_02):

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

每次調用格式存儲在SimpleDateFormatcalendar成員變量的日期,然後隨後將格式應用於calendar變量(而不是date參數)的內容。

因此,每次調用格式時,所有當前正在運行的格式的數據都可能會改變(取決於您的體系結構的一致性模型)每個其他線程使用的calendar成員變量中的數據。

所以,如果你運行多個併發調用格式化可能沒有得到一個例外,但每次通話可以返回從其他調用格式之一的日期得出的結果 - 或數據的混合組合從許多不同的調用格式。

相關問題