ThreadPool не выполняет задачи в последовательности - PullRequest
4 голосов
/ 17 декабря 2010

Я использую Executor рамки специально Executors.newCachedThreadPool();
У меня есть список Runnable с, например. 100.
Первые 50, каждое создает значение (хранится в списке) для использования последними 50.
Я думал, что если я передам Runnable в executor.execute() в том порядке, в котором они находятся в списке, они будут также выполняется в том же порядке.
Но этого не происходит.
Похоже, что задачи выполняются в случайном порядке, и они чередуются, а не выполняются последовательно.
Это как это должно работать? Есть ли способ обойти эту проблему?

Спасибо

Ответы [ 3 ]

10 голосов
/ 17 декабря 2010

Вам необходимо отправить задания в два пакета или иным образом создать явное отношение «происходит до». Предложите создать две партии заданий и использовать invokeAll(batch1); invokeAll(batch2); Метод invokeAll() выполнит все задачи и заблокирует их до завершения. Возможно, вам придется обернуть ваши Runnable s как Callable s, что вы можете сделать с Executors.callable(Runnable r). (@Cameron Skinner побеждает меня, чтобы получить пример кода, см. Ответ на этот вопрос подробнее ...)

Весь смысл исполнителей состоит в том, чтобы абстрагироваться от специфики исполнения, поэтому порядок не гарантируется, если явно не указано иное. Если вы хотите строго последовательное выполнение, сделайте это в потоке, в котором вы работаете (самый простой), сделайте это в однопоточном исполнителе, ala Executors.newSingleThreadExecutor(), или явно синхронизируйте задачи. Если вы хотите сделать последнее, вы можете использовать барьер или защелку и иметь блок зависимых задач на барьере / защелке. Вы также можете иметь первый блок задач, реализующий Callable, возвращающий Future, и вызывать зависимые задачи myFuture.get(), что заставит их блокироваться, пока не будут возвращены результаты.

Если вы скажете больше о вашем конкретном заявлении, мы сможем помочь вам более конкретно.

7 голосов
/ 17 декабря 2010

Это правильное поведение.У вас нет гарантии, в каком порядке выполняются Runnables.

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

Например,

for (Future<Whatever> f: service.invokeAll(first50tasks)) {
    addResultToList(f.get());
}
Future<Whatever> output = service.invokeAll(second50tasks);
2 голосов
/ 17 декабря 2010

Возможно, вы могли бы execute первые 50, shutdown и awaitTermination, и только потом execute остальные 50? См. этот ответ для примера кода.

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