Два потока пишут в один файл - PullRequest
1 голос
/ 19 ноября 2011

У меня есть несколько потоков (скажем, два, пока), каждый из которых извлекает HTML-страницу и записывает ее содержимое в файл. Предостережение заключается в том, что каждый поток хочет записать в один и тот же выходной файл. Класс с методом run () является статическим внутренним классом. Подход, который я хотел бы использовать, состоит в том, чтобы каждый поток помещал содержимое, которое он хочет записать, в очередь. Затем, после завершения потока (или завершения всех потоков), выполнить итерацию очередей и распечатать содержимое в файл. Я не уверен, как это реализовать. Опять же, класс, который реализует выполняемый интерфейс, является статическим Я не очень разбираюсь в параллелизме и не обязательно ищу что-то необычное. Любые предложения для простой реализации?

Ответы [ 4 ]

5 голосов
/ 19 ноября 2011

Вы можете использовать BlockingQueue из пакета java.util.concurrent. Каждый из ваших потоков помещает свои выходные данные в очередь, а третий поток извлекает элементы из очереди и записывает их в файл. На странице API для очереди блокировки приведен пример, который вы сможете использовать для своей реализации. Вам нужно только предоставить реализацию для produce и consume, и все готово.

3 голосов
/ 19 ноября 2011

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

static final ExecutorService logger = Executors.newSingleThreadExecutor();

static void writeToFile(final FileOutputStream fos, final String text) {
    logger.execute(new Runnable() {
        public void run() {
            try {
                fos.write(text.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}
0 голосов
/ 19 ноября 2011

Ну, исходя из вашего описания, я думаю, что ваши производители должны выглядеть так:

private static final int CAPACITY = 10; // whatever you like here.
private static Object locker = new Object();
private static Queue<String> queue = new ArrayBlockingQueue<String>(CAPACITY);

private static class ThreadTask implements Runnable {

    @Override
    public void run() {

        // retrieve page            
        // add result to queue
    }       
}

Конечно, вы можете выполнять эти ThreadTasks в Executor, чтобы лучше использовать системные ресурсы, а также ваш потребительский поток может работать одновременно с производителями, если вы реализуете систему очередей производитель-потребитель.

0 голосов
/ 19 ноября 2011

Вы можете также использовать synchronized блоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...