2016-06-19 68 views
1

我正在使用完成服務告訴我什麼時候一組文件已成功加載。 這是讀取文件的方法:使用Java IO返回讀取文件的「不可能」null null

public static LocalDateColumn readLocalDateColumn(String fileName, ColumnMetadata metadata) throws IOException { 
    LocalDateColumn dates = new LocalDateColumn(metadata); 
    assert(dates != null); 
    try (FileInputStream fis = new FileInputStream(fileName); 
     SnappyFramedInputStream sis = new SnappyFramedInputStream(fis, true); 
     DataInputStream dis = new DataInputStream(sis)) { 
     boolean EOF = false; 
     while (!EOF) { 
     try { 
      int cell = dis.readInt(); 
      dates.add(cell); 
     } catch (EOFException e) { 
      EOF = true; 
     } 
     } 
    } 
    //System.out.println(dates); 
    return dates; 
    } 

注意日期分配由斷言檢查中的第一個語句的值。還要注意倒數第二行:註釋掉的打印語句。當此語句是而不是註釋掉時,返回值不會爲空。當它被註釋掉時,它在相同數據上運行的時間的1/2左右。

幫助將不勝感激。

順便說一句。使用EOF異常捕獲來查找文件的結尾看起來很難看,但Snappy要求它正確操作。我在其他代碼中使用它,它一直工作正常。

FWIW,上面的代碼使用CompletionService 它看起來像這家名爲:

List<Column> columnList = new ArrayList<>(); 
try { 
    for (ColumnMetadata column : columnMetadata) { 
    readerCompletionService.submit(() -> { 
     columnList.add(readColumn(path + File.separator + column.getId(), column)); 
     return null; 
    }); 
    } 
    for (int i = 0; i < columnMetadata.size(); i++) { 
    Future future = readerCompletionService.take(); 
    future.get(); 
    } 
    for (Column c : columnList) { 
    columns.put(c.id(), c); 
    } 

在那裏執行到最後一行的點。即:

columns.put(c.id(), c); 

c有時爲空。

+3

當println(它是一個同步方法)改變你的併發程序時,可能的結論是有一個競爭條件,它被額外的同步解決/隱藏。 – assylias

+0

你真的運行你的Java運行時啓用斷言('-ea'參數到Java可執行文件)? –

+0

例如,雖然ArrayList不是線程安全的,但columnList同時使用... – assylias

回答

1

您同時使用ArrayList但該集合不是線程安全的。您應該嘗試使用線程安全集合,例如CopyOnWriteArrayList