Один пул потоков против одного пула потоков на задачу

Я хочу использовать параллелизм в Java, чтобы делать запросы к онлайн-API, загружать и анализировать документы ответов и загружать полученные данные в базу данных.

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


person user1660310    schedule 10.09.2012    source источник
comment
В конвейерной модели (т. е. с тремя пулами) вам, возможно, придется определить оптимальное соотношение размеров пулов или динамически изменять размеры пулов, чтобы обеспечить их сбалансированность. т. е. вам нужно задать себе такие вопросы, как Если у меня есть 10 параллельных потоков загрузки, сколько параллельных потоков анализа мне нужно, чтобы гарантировать, что очередь загрузки-анализа поддерживает более или менее постоянный размер?   -  person ArjunShankar    schedule 10.09.2012


Ответы (3)


Вы должны учитывать, какие части обработки выиграют от параллелизма. Онлайн-связь API, скорее всего, будет кандидатом, поскольку будут задействованы сокеты и сетевые ожидания. Аналогично с взаимодействием с БД. Многопоточный синтаксический анализ, вероятно, повысит производительность только при наличии нескольких доступных ядер ЦП.

Разделение всего процесса на 3 отдельных класса определенно повысит сплоченность, а это означает, что у каждого класса будет меньше обязанностей, и это хорошо. С другой стороны, превращение каждого из этих классов в Runnable и наличие нескольких очередей усложнит (возможно, излишне) приложение.

Я бы предложил сделать 3 отдельных класса, но не делать их Runnable. Затем сделайте Runnable, что contains и orchestrates 3 класса, то есть один пул потоков. Если вы видите, что это кажется недостаточно быстрым (и после некоторого профилирования), попробуйте разделить исполняемый файл на 2 пула потоков: загрузка и синтаксический анализ и доступ к базе данных.

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

person Brady    schedule 10.09.2012

Важно учитывать один важный момент: имеет ли значение порядок обработки? т. е. важно ли, чтобы проанализированный результат первого запроса на загрузку загружался в БД до результатов второго запроса?

Если это так, вам действительно нужны очереди (или подобные), по одной на задачу. По сути, три однопоточных «пула» потоков (или используют ExecutorService).

Если нет, @Brady делает хорошие выводы. В отличие от него, я бы, вероятно, сделал все три класса Runnable, но это не значит, что вам нужно использовать три очереди, вы все равно можете попробовать один пул и профиль, чтобы увидеть, как это работает.

person user949300    schedule 10.09.2012

Я не верю, что существует стандартный подход, это зависит от ваших требований.

Если вы пишете что-то быстрое и грязное, вам лучше иметь один пул.

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

person TedTrippin    schedule 10.09.2012