Разумное количество потоков для пула потоков, выполняющих запросы веб-службы - PullRequest
16 голосов
/ 22 июня 2009

При создании объекта FixedThreadPool Executor в Java вам нужно передать аргумент, описывающий количество потоков, которые Executor может выполнять одновременно. Я строю сервисный класс, в обязанности которого входит обработка большого количества телефонных номеров. Для каждого номера телефона мне нужно запустить веб-сервис (это мое узкое место), а затем сохранить ответ в хэш-карте.

Чтобы сделать это узкое место менее вредным для производительности моего сервиса, я решил создать класс Worker, который выбирает необработанные элементы и обрабатывает их. Класс Worker реализует интерфейс Runnable, и я запускаю Workers с помощью Executor.

Количество рабочих, которые могут быть запущены одновременно, зависит от размера Executor FixedThreadPool. Какой безопасный размер для ThreadPool? Что может произойти, когда я создаю FixedTheradPool с большим числом в качестве аргумента?

Ответы [ 9 ]

8 голосов
/ 12 июля 2010

Что-то, что можно рассмотреть, смотрит на

Runtime.getRuntime().availableProcessors()

, в котором указано, сколько потоков имеет смысл для системы.

6 голосов
/ 22 июня 2009

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

2 голосов
/ 22 июня 2009

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

2 голосов
/ 22 июня 2009

Если у вас есть доступ dev к веб-службе, рассмотрите возможность создания пакетной функции для проверки нескольких телефонных номеров за один звонок.

В более новых .NET есть ThreadPool, который может увеличиваться и уменьшаться в зависимости от собственного профиля производительности. К сожалению, версия Java либо исправлена, либо увеличивается до предела в зависимости от поступающей работы.

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

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

2 голосов
/ 22 июня 2009

Я где-то читал, что оптимальное количество потоков - это количество ядер * 25. Похоже, что .NET использует это по умолчанию для ThreadPool. Однако, если у вас большое количество вызовов веб-служб, вам лучше использовать один поток и проверить список вызовов веб-служб для получения ответа. После получения ответа просто обработайте запись и удалите ее из списка.

1 голос
/ 23 июня 2009

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

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

В соответствии с этими допущениями вы не сможете максимизировать пропускную способность многоядерного процессора для любого разумного размера пула потоков. Для достижения максимального количества транзакций в секунду вы должны разбить поток на модель соединения. Найдите упомянутый ранее неблокирующий ввод-вывод (NIO) или Java-реализацию шаблона токена асинхронного завершения (IO-завершение в Windows).

Обратите внимание, что стековая память, зарезервированная для каждого созданного потока, на самом деле просто зарезервирована адресное пространство , а не фактически выделенная или зафиксированная память. По мере того, как стек пытается расти, генерируются исключения, в результате чего память стека фиксируется по требованию. Следствием этого является то, что это действительно актуально только для 32-битных менеджеров памяти. Для 64-битной памяти у вас есть огромное адресное пространство, даже если вы зарезервировали только небольшую часть этого пространства физической памятью. По крайней мере, я так понимаю, что Windows работает, я не уверен в мире Unix.

0 голосов
/ 22 июня 2009

Если вы выполняете тяжелые вычисления, скажем, для манипуляций с параллельными массивами, то практическим правилом является количество потоков для числа процессоров.

0 голосов
/ 22 июня 2009

Интересно, будет ли вам лучше использовать NIO, а не потоки, поскольку вашим ограничивающим фактором будет сервер веб-службы + узкое место в сети, а не клиентский ЦП.

В противном случае вы не должны превышать количество одновременных подключений, которые может поддерживать ваша веб-служба.

0 голосов
/ 22 июня 2009

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

Этот размер стека настраивается через -Xss (аналогично -Xmx и т. Д.). Я считаю, что по умолчанию 512Kb на поток. В настоящее время я не могу найти какого-либо авторитетного лица, подтверждающего это.

...