Невозможно сказать, будут ли 300 или даже 3000 потоков вызывать какие-либо проблемы, не зная больше о вашем приложении. Я настоятельно рекомендую вам профилировать ваше приложение, прежде чем добавлять больше сложности
Первое, что вы должны проверить, это то, что количество одновременно работающих потоков не должно быть намного больше, чем количество ядер, доступных для запуска этих потоков. Чем больше у вас активных потоков, тем больше времени тратится на управление этими потоками (переключение контекста обходится дорого), и тем меньше работа выполняется.
Самый простой способ ограничить количество запущенных потоков - использовать семафор. Приобретите семафор перед началом работы и отпустите его после завершения работы.
К сожалению, ограничения количества работающих потоков может быть недостаточно. Хотя это может помочь, накладные расходы все еще могут быть значительными, если время, затрачиваемое на переключение контекста, составляет основную часть общей стоимости одной единицы работы. В этом случае часто наиболее эффективным способом является фиксированное количество очередей. Вы получаете очередь из глобального пула очередей, когда компонент инициализируется с использованием алгоритма, такого как циклический перебор для выбора очереди.
Если вы находитесь в одном из тех неудачных случаев, когда наиболее очевидные решения не работают, я бы начал с чего-то относительно простого: один пул потоков, одна параллельная очередь, блокировка, список очередей и временная очередь для каждого потока в пуле.
Размещать работу в очереди просто: добавьте полезную нагрузку и личность производителя.
Обработка также относительно проста. Сначала вы получаете следующий элемент из очереди. Тогда вы приобретаете замок. Пока у вас есть блокировка, вы проверяете, выполняет ли какой-либо другой поток задачу для того же производителя. Если нет, вы регистрируете поток, добавляя временную очередь в список очередей. В противном случае вы добавляете задачу в существующую временную очередь. Наконец вы отпускаете замок. Теперь вы либо запускаете задачу, либо проводите опрос для следующего и начинаете сначала, в зависимости от того, был ли зарегистрирован текущий поток для запуска задач. После выполнения задачи вы снова получаете блокировку и видите, нужно ли выполнять дополнительную работу во временной очереди. Если нет, удалите очередь из списка. В противном случае получите следующее задание. Наконец вы отпускаете замок. Опять же, вы выбираете, запускать задачу или начинать заново.