Приведи пример, когда важно иметь выделенное число тредов и много задач для обработки в веб-сервисе
Что проверяют
Понимаете ли, зачем в пуле фиксируют число потоков, и знаете ли, что в CPython потоки ускоряют не всякую работу. Вопрос сразу вытаскивает наружу, различаете ли вы задачи, которые ждут ввода-вывода, и задачи, которые считают процессором.
Как отвечать
Хороший пример: сервис собирает ответ из нескольких внешних источников, на каждый пользовательский запрос приходится несколько сетевых вызовов, каждый ждёт ответа сотни миллисекунд. Работа тут не в процессоре, а в ожидании: на время сетевого вызова поток отпускает глобальную блокировку, поэтому пул из десятков потоков честно ускоряет обработку.
Фиксированный размер нужен не ради скорости, а ради ограничения:
- у базы конечный пул соединений, и лишние потоки просто встанут за ним в очередь, добавив таймауты;
- у стороннего API есть лимит обращений, превышать его нельзя;
- каждый поток это стек в памяти плюс переключения контекста;
- очередь задач должна быть ограниченной, иначе при наплыве сервис копит работу, пока не кончится память.
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(max_workers=16) # ровно столько, сколько держит базаТак пул превращается в регулятор: задач много, исполнителей ровно столько, сколько выдерживает самое узкое место, а отказ приходит быстро вместо зависания на минуту.
Где спотыкаются
Приводят в пример обработку изображений или другую счётную задачу и обещают ускорение. В CPython глобальная блокировка пускает в байт-код один поток за раз, и такой пул даёт только накладные расходы. Счётное идёт в ProcessPoolExecutor или в библиотеку, которая отпускает блокировку внутри сишного кода.
Второе: ставят число воркеров наугад побольше. Отправная точка привязана к узкому месту: размеру пула соединений, лимиту стороннего сервиса, числу ядер для счётной работы. Дальше замер под нагрузкой, а не догадка.
Третье: забывают, что общее состояние в пуле надо защищать. Привычное counter += 1 это чтение, сложение и запись, между которыми поток могут прервать. Возвращать результат через Future безопаснее, чем писать в общий словарь.