Что произойдет, когда для invokeAll () будет меньше потоков, чем число задач? - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть код ниже:

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                                                10, // corePoolSize
                                                10, // maximumPoolSize
                                                10, // keepAliveTime
                                                TimeUnit.SECONDS, 
                                                new LinkedBlockingQueue<>()
                                        );

final List<Callable<MyResponse>> tasks = new ArrayList<>();
final CountDownLatch latch = new CountDownLatch(concurrency);

for (int i = 0; i < 50; i++) {
    tasks.add(() -> {
        latch.countDown();
        latch.await();

        return getResponse(); // Returns a MyResponse object.
    });
}

final List<Future<ThrottleResponse>> futures = threadPoolExecutor.invokeAll(tasks);

Есть 50 задач, но доступно только 10 потоков.Исходя из результатов моих тестов, выполнение кода занимает вечность, чего я не понимаю.

Что происходит с методом invokeAll?Есть ли в этом коде мертвая блокировка и почему?Я думаю, что threadPoolExecutor будет помещать отложенные задачи в LinkedBlockingQueue и опрашивать их в очереди для выполнения задач, так что не должно быть мертвой блокировки, верно?

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

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

Что вы сделали, так этописать задачи, которые не будут выполнены до тех пор, пока не начнутся все остальные задачи.Поскольку у вас есть 10 рабочих, первые 10 задач начинаются с одного рабочего ... и затем ждут.Первые 10 не могут завершиться, потому что они ждут запуска других задач, а другие задачи не могут быть запущены, потому что исполнитель ожидает освобождения работника ... и этого не произойдет, пока один из первых 10задачи завершены.Deadlock.


Вы прокомментировали:

Я думаю, что threadPoolExecutor поместил бы ожидающие задачи в LinkedBlockingQueue и произвел бы опрос из очереди для выполнения задач, поэтому не должно быть мертвыхlock right?

Все задачи поставлены в очередь правильно.Проблема в том, что сами задачи делают после того, как они были поставлены в очередь;см. объяснение выше.


Решения:

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

  • Если вам придется ждать запуска других задач, увеличьтеразмер пула потоков настолько велик, что он может одновременно выполнять все задачи .

0 голосов
/ 06 декабря 2018

, поскольку каждая задача заблокирована в "latch.await ();", задачи в очереди в LinkedBlockingQueue <> никогда не будут иметь шансов на выполнение.это делает тупики.Вы должны latch.countDown () в каждой задаче.но latch.await () в основном потоке.

...