Implement run_limited(tasks, k) -> list:
tasksis a list of zero-argument functions (think: downloads that each need one ofknetwork connections).- Start one thread per task, all right away, but let at most
ktasks run at the same time. A thread that can't run yet waits until a running task finishes. - Return the list of results in the same order as
tasks(results[i] = tasks[i]()), once every task has finished.
run_limited([lambda: 1, lambda: 2, lambda: 3], 2) # [1, 2, 3], never more than 2 running
run_limited([], 3) # []
With 6 tasks that each take 0.1s and k = 2, the whole call takes about 0.3s: never more than 2 at once, but always 2 when there are 2 waiting.
Constraints: 1 <= k, 0 <= len(tasks) <= 50. k may be larger than the number of tasks. Don't sleep or busy-wait.
Show hint
A threading.Semaphore(k) holds k permits: each thread does with sem: around its task, so the (k+1)-th thread blocks in acquire until someone releases.