Forgive the title if it isn't correct, I am just not sure what I am trying to design is called.
Say I have a number of tasks I want to run, N.
Additionally, I have a maximum number of threads I can allocate at once, T.
I want to run as many of these tasks in async as I have threads available (up to T), and once a thread frees up I want to immediately start a new task on the thread that just finished until all tasks have been run.
EXAMPLE
say I have 10 tasks to run and 4 threads available to run these tasks. As the app starts, 4 threads begin running 4 of the 10 tasks, leaving 6 remaining tasks, when one of the running tasks finishes, immediately another task starts running on a new thread and there are 5 remaining tasks. This goes on until there are no more remaining tasks to execute.
QUESTION
Is there a design pattern or common application architecture I can study to build a task runner like this?