アプリの I/O の速度を上げようとしているので、複数のスレッドを使用して保存することにしました。ファイルは book/symbol/file という階層で構造化されており、複数のスレッドが同じディレクトリに複数のファイルを同時に保存する可能性があります。すべてのファイルを順番に保存すると問題ありません。ただし、複数のスレッドが起動すると、ファイルの形式が正しくなく、そのファイルをロードすると「IOException : 無効なブロック」が発生することがあります。この場合、同時実行が問題を引き起こす可能性がある理由はありますか?
以下のコード:
private void storeAppendingTimestamps(Series timeSeries) throws MetricPersistException {
Metric metric = timeSeries.getMetric();
Path outPutFile;
try {
outPutFile = generateOutputFilePath(metric);
if (!Files.exists(outPutFile)) {
createNewFile(outPutFile);
}
} catch (IOException e) {
throw new PersistException("Cannot create output file for metric " + metric);
}
try (PrintWriter writer = new PrintWriter(new GZIPOutputStream(new FileOutputStream(outPutFile.toFile(), true)), true)) {
for (SeriesDataPoint dataPoint : timeSeries.getTimeSeriesPoints()) {
writer.println(String.format("%d %s", dataPoint.getTimestamp().getMillis(), formatPlain(dataPoint.getValue())));
}
writer.close();
} catch (IOException e) {
throw new MetricPersistException(String.format("IO Exception has occured while persisting metric %s: %s", metric, e.getMessage()));
}
}
そして、作業を分割するコード:
private void persistTimeSeries(Collection<Series> allSeries, CompletionService<Void> executorService) throws MetricPersistException {
final LoggingCounter counter = new LoggingCounter(logger, "metric series file", 10000);
for (final MetricTimeSeries series : allSeries) {
executorService.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
persister.persistTimeSeries(series);
counter.increment();
return null;
}
});
}
for (int i = 0; i < allSeries.size(); i++) {
Future<Void> future = executorService.take();
future.get();
}
counter.finish();
}