Write an application that handles a queue of jobs in N=5 threads. Each job contains a number between 0-5. Each thread takes the next element from the queue and sleeps for the given amount of second (as an imitatin of actual work it should be doing). When finished it check for another job. If there are no more jobs in the queue, the thread can close itself.

from __future__ import print_function
import threading, random, sys
print = lambda x: sys.stdout.write("{}\n".format(x))

thread_count = 5

counter = 0
queue = map(lambda x: ('main', random.randrange(5)), range(20))

If that's done, change the code so that each thread will generate a random number between 0-5 (for sleep-time) and in 33% of the cases it will add it to the central queue as a new job.

Another extension to this exercise is to change the code to limit the number of jobs each thread can execute in its lifetime. When the thread has finished that many jobs it will quit and the main thread will create a new worker thread.