Есть ли исполнитель в параллельном пакете Java, который гарантирует, что все задачи будут выполнены в том порядке, в котором они были представлены? - PullRequest
2 голосов
/ 23 февраля 2012

Пример кода для демонстрации идеи из заголовка:

executor.submit(runnable1);
executor.submit(runnable2);

Мне нужно быть уверенным, что runnable1 завершится до запуска runnable2, и я не нашел никаких доказательств такого поведения у исполнителейдокументация.

О проблеме, которую я решаю: мне нужно записать много файлов в файл.Каждый журнал требует много предварительных вычислений (форматирование и некоторые другие вещи).Итак, я хочу поместить каждую задачу регистрации в своего рода очередь и обрабатывать эти задачи в отдельном потоке.И, конечно же, важно следить за порядком ведения логов.

Ответы [ 3 ]

4 голосов
/ 23 февраля 2012

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

Добавление задач в очередь само по себе может быть дорогостоящим. Вы можете использовать обменник как этот

http://vanillajava.blogspot.com/2011/09/exchange-and-gc-less-java.html?z#!/2011/09/exchange-and-gc-less-java.html

Это позволяет избежать использования очереди или создания объекта.

Альтернативой, которая является более быстрой, является использование файла отображения памяти, который не требует фонового потока (фактически ОС работает в фоновом режиме). Это снова намного быстрее. Он поддерживает субмикросекундные задержки и миллионы сообщений в секунду.

https://github.com/peter-lawrey/Java-Chronicle

0 голосов
/ 23 февраля 2012

Предположительно, вы делаете какой-то пост-анализ файла журнала?Считаете ли вы, что не заботитесь о том, что они написаны, и о том, чтобы сделать заказ позже.Вы можете выделить уникальный идентификатор во время отправки, используя метку времени или AtomicLong?

эскиз кода (не проверенный) будет выглядеть так:

import java.util.concurrent.atomic.AtomicLong;

class MyProcessor {

    public void work()
        for (Object data: allData) {
            executor.submit(new MySequencedRunnable(data);
        }
    }

}

class MySequencedRunnable implements Runnable {
    private static final AtomicLong LOG_SEQUENCE_ID = new AtomicLong(0);

    private final Object data;

    MySequencedRunnable(Object data) {
       this.data = data;

    }

    public void run() {
        LOGGER.log(LOG_SEQUENCE_ID.incrementAndGet(), data);
    }

}

ТакжеЕсли вы используете что-то вроде log4j, используйте NDC или MDC , чтобы помочь с переупорядочением.

0 голосов
/ 23 февраля 2012

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

class MyRunnable implements Runnable {

    private List<Runnable> runnables = new ArrayList<>();

    public void add(Runnable r) {
        runnables.add(r);
    }
    @Override
    public void run() {
        for (Runnable r : runnables) {
            r.run();
        }
    }

}

//......
MyRunnable r = new MyRunnable();
r.add(runnable1);
r.add(runnable2);
executor.submit(r);    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...