Почему invokeAll не удается с ExecutorService с ограниченным размером пула - PullRequest
1 голос
/ 18 июня 2019

У меня есть класс, который использует ExecutorService для выполнения URL-запросов, чтобы они могли выполняться параллельно, и я ограничиваю его максимальным размером пула 20

private static ExecutorService getCachedPool(ThreadFactory threadFactory)
{
    return new ThreadPoolExecutor(20, 20,
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(),
            threadFactory);
}

Однако я использую его следующим образом:

List<Future<ArtistCoverImage>> results = ArtistArtworkOnlineLookup.getExecutorService()
    .invokeAll(lookups);

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

Если я просто изменю на максимальный размер пула Integer.MAX_VALUE

private static ExecutorService getCachedPool(ThreadFactory threadFactory)
    {
        return new ThreadPoolExecutor(20, Integer.MAX_VALUE,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(),
                threadFactory);
    }

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

1 Ответ

4 голосов
/ 18 июня 2019

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

javadoc сообщает нам:

Новые задачи, отправленные в метод execute, (java.lang.Runnable) будут отклонены после закрытия Executor,а также, когда Исполнитель использует конечные границы как для максимальных потоков , так и для емкости рабочей очереди, и насыщается.

Но, что более важно, javadoc для SynchronousQueue сообщает:

Очередь блокировки, в которой каждая операция вставки должна ожидать соответствующую операцию удаления,другой поток, и наоборот.

Когда вы вводите в него 20 длительных задач, каждое из них переходит в поток.Когда они все еще работают, когда входит # 21, пул полностью используется, и очередь сразу говорит: «Я тоже полон».Все насыщено, новая работа больше не принимается.

Решение: выберите другой тип очереди.

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