У меня есть объект класса, который действует как сервер. Он получает запрос отовсюду и помещает запрос в свою очередь запросов (Producer
). Теперь запущен потребительский поток, который извлекает запрос из очереди запросов и на основе запроса вызывает соответствующий метод класса для предоставления запроса. Теперь потребление запроса из очереди и запуск соответствующей функции выполняется синхронно. Я хочу, чтобы потребительский поток выскакивал запрос из очереди и запускал соответствующую функцию асинхронным образом, чтобы потребитель мог немедленно получить следующий запрос из очереди.
Одно из решений, которое я попробовал, заключается в том, что потребитель выскакивает запрос из очереди и создает boost::thread
и запустить соответствующую функцию в новом потоке. Я сохранил указатели потока в std::vector
как и пытался boost::thread_group
, Все идет нормально. Но есть проблема в этом решении.
После того как я предоставил более 150 запросов, есть более 150 потоков, и после этого pthread
не создает новый поток, выдающий ошибку "pthread_create: Resource temporarily unavailable"
, что, я считаю, означает, что стек текущего процесса исчерпан, поэтому новые потоки не могут быть созданы.
Вопрос 1 Мой обработчик запросов не содержит while (1)
и те просто делают некоторую работу и выходят и вообще ничего не ждут, поэтому я ожидаю, что мои начальные потоки завершили свою обработку и вышли из функции обработчика потоков. Учитывая это, если поток завершил свою обработку и завершил работу, не должен ли он очистить свои данные из стека?
Одним из решений этой проблемы является то, что я могу установить размер стека потока, но это все равно вызовет эту ошибку после, скажем, 1000 потоков.
Поэтому мое требование состоит в том, чтобы через некоторое время я должен был очистить завершенные потоки (например, когда вектор указателей потока превысил 100 или через каждую 1 минуту или что-то в этом роде).
Вопрос 2 Помимо запуска нового потока, как я уже упоминал выше, какой другой механизм вызова асинхронных функций я должен попробовать. Является boost::function
+ boost::bind
асинхронный? Это хорошее решение ситуации, о которой я говорил? Скажем, моя система должна быть в сети 24/7/365 и получать, скажем,> 1000 запросов каждый день.
Обновление № 1
Так что я нашел одну проблему в своем дизайне. Я упомянул в своем вопросе № 1, что мой обработчик запросов содержит только простые вызовы, которые, как я обнаружил, не соответствуют действительности. Он загружает файл с сервера синхронно, что по сути является операцией блокировки. Я должен загрузить файл асинхронно.
Нет смысла создавать потоки, которые ваша базовая система не может обрабатывать одновременно, если обработчик запросов не выполняет никаких операций блокировки.
Так как Алекс упомянул наличие более чем одного потока пользователя (я думаю, что 5 достаточно) для извлечения запроса из очереди и асинхронной загрузки файла, решит мою проблему.
Одно из решений состоит в том, чтобы иметь несколько потоков потребителей, каждый из которых извлекает рабочий элемент из очереди и обрабатывает его синхронно. Это позволяет вам управлять параллелизмом (избегать чрезмерной подписки), одновременно обрабатывая несколько элементов одновременно. Вы также снимаете накладные расходы на запуск нового потока для каждого элемента, который, как я предсказывал, является одним из ваших узких мест.
Вы должны убедиться, что ваша очередь предназначена для нескольких потребителей.
Никогда не использовался эта реализация, но пул потоков может помочь.
Вы уже используете Boost и загружаете файлы. Поэтому было бы вполне естественно использовать Boost.Asio для работы в сети и для всех других вещей, связанных с многопоточностью / асинхронностью, таких как центральный диспетчер.
Прежде всего, я бы рекомендовал создать пул потоков и запустить диспетчер Asio над ними: как здесь. Используйте асинхронную сеть Asio для загрузки файлов: пример здесь. Когда файл загружен, просто обработайте его.
Этот подход довольно масштабируемый, и вы не будете беспокоиться об асинхронной сети или многопоточной синхронизации (довольно сложная штука). Boost.Asio предоставляет хорошие примеры, как этого добиться.