2016-06-19 5 views
1

Ich verwende einen Completion Service, um mir mitzuteilen, wenn eine Gruppe von Dateien erfolgreich geladen wurde. Dies ist die Methode, die die Datei lautet:Ein "unmögliches" null gab Lesedateien mit Java IO zurück

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; 
    } 

Hinweis, die einen Wert in der ersten Anweisung zugeordnet Daten, die durch eine Behauptung überprüft wird. Beachten Sie auch die vorletzte Zeile: Die auskommentierte Print-Anweisung. Wenn diese Anweisung nicht auskommentiert ist, ist der Rückgabewert nie null. Wenn es auskommentiert ist, ist es ungefähr die Hälfte der Zeit, die auf den gleichen Daten läuft.

Hilfe wäre sehr willkommen.

BTW. Die Verwendung des EOF-Exception-Catching, um das Ende der Datei zu finden, sieht hässlich aus, wird aber von Snappy für den korrekten Betrieb benötigt. Ich habe es in anderem Code verwendet und es hat immer gut funktioniert.

FWIW, Der obige Code wird mit einem CompletionService genannt Es sieht wie folgt aus:

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); 
    } 

An dem Punkt, an dem die Ausführung die letzte Zeile erreicht. Das heißt:

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

c manchmal null ist.

+3

Wenn println (was eine synchronisierte Methode ist) Ihr paralleles Programm ändert, ist die wahrscheinliche Schlussfolgerung, dass es eine Race-Bedingung gibt, die durch die zusätzliche Synchronisation gelöst/versteckt wird. – assylias

+0

führen Sie Ihre Java-Laufzeit tatsächlich mit aktiviertem Assertions ('-ea' Argument zu ausführbarem Java)? –

+0

Zum Beispiel wird columnList gleichzeitig verwendet, obwohl ArrayList nicht Thread-sicher ist ... – assylias

Antwort

1

Sie verwenden eine ArrayList gleichzeitig, aber diese Sammlung ist nicht threadsicher. Sie sollten stattdessen versuchen, eine Thread-sichere Sammlung zu verwenden, z. B. CopyOnWriteArrayList.

Verwandte Themen