Надежная запись из нескольких потоков в один PrintWriter - PullRequest
0 голосов
/ 15 октября 2011

Я столкнулся с проблемой, когда у меня есть несколько потоков, которые пишут в один и тот же PrintWriter, и не все данные записываются в файл. Я знаю, что многопоточная часть работает правильно, так как я могу печатать все на консоли. Синхронизация операторов записи, похоже, не работает. В чем может быть проблема?

ExecutorService pool = Executors.newFixedThreadPool(poolSize);

for (Integer i : map.keySet()) {
    final Collection<String[]> set = map.get(i);
    pool.submit(new Runnable() {
        public void run() {
        StringBuffer sb = Matcher.performCollectionMatch(params);
        synchronized (this) {
            resultFile.print(sb); //this is a PrintWriter - it does NOT capture all sb
            resultFile.flush();
            System.out.print(sb); //this actually prints out ALL sb
        }
        }
    });
} //FOR loop

Ответы [ 3 ]

4 голосов
/ 15 октября 2011

Чтобы синхронизация работала, вы должны использовать один и тот же объект для всех потоков, например ::100100

...
synchronized (resultFile) {
...
3 голосов
/ 15 октября 2011

Вы закрываете PrintWriter после остановки бассейна?

pool.shutdown();
final boolean terminated = pool.awaitTermination(8, TimeUnit.SECONDS);
if (!terminated) {
    throw new IllegalStateException("pool shutdown timeout");
}

resultFile.close();
1 голос
/ 15 октября 2011

Более простое решение - обеспечить наличие только одного потока в пуле.Таким образом, вам не нужно синхронизировать запись, поскольку существует только один поток.

ExecutorService pool = Executors.newSingleThreadedPool();

for (Integer i : map.keySet()) {
    final Collection<String[]> set = map.get(i);
    pool.executor(new Runnable() {
        public void run() {
            StringBuilder sb = Matcher.performCollectionMatch(params);
            resultFile.print(sb); //this is a PrintWriter - it does NOT capture all sb 
            System.out.print(sb); //this actually prints out ALL sb
        }
    });
} //FOR loop

Вполне вероятно, что проблема заключается в доступе к диску, поэтому добавление дополнительных потоков может не помочь.

...