Лучший способ (на мой взгляд) - создать очередь, содержащую задания, а затем запустить десять потоков, которые просто читают следующую очередь из очереди и обрабатывают ее.
Преимущество заключается в минимальных затратах на создание / удаление потоков и автоматическом распределении рабочих нагрузок между потоками. Под этим я подразумеваю потоки, которые быстро получают задания, автоматически получают больше заданий для работы.
Затем, в конце этих 10000 заданий, вы помещаете 10 заданий завершения, которые приведут к выходу рабочего потока, а затем ожидаете их.
Вся схема выглядит так:
main thread:
create a queue
do ten times:
start a worker thread
do ten thousand times:
add normal job to queue
do ten times:
add shutdown job to queue
wait for all workers to finish
exit
worker thread:
while true:
get job from queue
if job is shutdown job:
exit
process job
Очевидно, что доступ к очереди должен быть защищен мьютексом, чтобы избежать условий гонки.
Одна вещь, которую вы должны иметь в виду, хотя. Если задачи требуют интенсивной загрузки ЦП, вы не получите никакой реальной выгоды от наличия большего количества потоков, чем доступного исполнительного блока (процессоров или ядер или чего-либо еще).
Например, если у вас есть только одно ядро, самый быстрый способ сделать то, что вы хотите, это просто вообще не использовать потоки. Использование потоков в таких задачах, интенсивно использующих процессор, на самом деле, вероятно, будет на медленнее , поскольку вы вводите накладные расходы на переключение задач.