2012-04-14 4 views
6

В моем проекте я создаю среду выполнения Java, которая получает рабочие запросы от клиента. Работа (разный размер) разбивается на набор задач и затем помещается в очередь для обработки. Существуют отдельные очереди для обработки каждого типа задачи, и каждая очередь связана с ThreadPool. ThreadPools настроены таким образом, что общая производительность двигателя оптимальна.Work/Task Stealing ThreadPoolExecutor

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

Чтобы сделать это лучше, я думал о внедрении техники кражи работы/задачи, чтобы тяжело загруженная очередь могла получить помощь от других ThreadPools. Однако для этого может потребоваться реализация моего собственного Executor, поскольку Java не позволяет связать несколько очередей с ThreadPool и не поддерживает концепцию кражи работы.

Читайте о Fork/Join, но это не похоже на мои потребности. Любые предложения или альтернативный способ создания этого решения могут быть очень полезными.

Благодаря Энди

+1

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

+0

Если в ваших пулах потоков столько потоков, сколько у вас есть, любой отдельный пул потоков может «украсть» весь процессор, даже если все остальные пулы потоков простаивают. –

+0

@PeterLawrey - это правда, но если есть много пулов, то у вас может быть низкая производительность, если все потоки во всех пулах работают одновременно. – jtahlborn

ответ

1

вы могли бы реализовать реализацию пользовательских BlockingQueue (я думаю, что вы в основном должны реализовать offer() и take() методы), который при поддержке «основной» очереди и 0 или более вторичных очередей. take всегда берет из основной очереди поддержки, если не пуст, иначе он может вытащить из вторичных очередей.

Фактически, может быть лучше иметь 1 пул, где все рабочие имеют доступ ко всем очередям, но «предпочитают» определенную очередь. вы можете придумать оптимальный коэффициент работы, назначив разные приоритеты различным работникам. в полностью загруженной системе ваши работники должны работать с оптимальным соотношением. в недогруженной системе ваши работники должны иметь возможность помогать другим очередям.

+0

Это кажется хорошей идеей, которую я склоняюсь, чтобы попробовать с POC. –

2

Вы считаете ForkJoinPool? Структура fork-join была реализована с использованием модульной модуляции, поэтому вы можете просто использовать пул потоков, скрывающий работу.

+1

Прочтите API, но до сих пор не можете понять, как он отличается от обычного ThreadPoolExecutor. Возможно, там нет более тонких аспектов. –

+0

Да, я вижу, что у вас есть схема разделения, которую вы сейчас хотите сделать гибкой - пусть границы разделов смещаются в соответствии с рабочей нагрузкой. «Кража работы» может быть более специализированным термином для схем, которые включают точное гранулометрическое задание - задача, выполняемая в одном потоке, генерирует подзадачи и подталкивает их к собственному деку, чтобы другие потоки могли украсть ее работу. Так что, возможно, если вы исследуете термин «разделение пула потоков», вы найдете что-то подходящее для вашего дела. –

2

Java 8 имеет заводские и служебные методы для этого в классе Executors. Существует реализация пула потоков обработки (here), который, я считаю, именно то, что вы хотите.

+0

Единственный недостаток, который я вижу в этом, заключается в том, что он создает новые ForkJoinThreads по требованию вместо заимствования этих потоков из глобального пула - может быть общим пулом или пулом, который может пройти клиент. –

Смежные вопросы