metulburr wrote:Not that a single while loop is much of a resource, but it seems like wasted resources for switching between while loops for each thread. However i could see this useful if you need to swtich between these like switches. I was thinking more of a one time thread run and then its killed.
So i guess my understanding of it is:
You reuse the thread instead of creating a new one for each operation you want or relevant operation, whatever.
My example illustrates a case where the thread is running a continuous task that never terminates (such as continuously monitoring a directory), or a long-running task that can be broken down into discrete steps (which case you would perform a single step inside the while loop and break out of the loop when the step is done). In these cases, the nature of the task is already iterative, so the while loop doesn't really add anything extra. Note that you never actually "switch" between the while loops -- each loop runs in its own thread.
The while loop is necessary for the graceful termination of the thread. Only the thread itself knows what stage of execution it is in, what resources it is currently holding, and what is necessary to clean up before termination. Therefore the only way to achieve graceful termination is to signal the thread to shut down and wait for it to do its own cleanup. If you don't care about graceful termination, then just use daemon threads -- the daemons with simply be killed when the main exits.
My example only deals with a single perpetual/long-running task per thread (since this is when you would typically want to kill a thread, rather than wait for it to finish). The example can be adapted to reuse the same thread for performing several operations by adding a Queue and modifying the run() logic; but if that is what you want, then you should be using a pool, as illustrated by Yoriz
. The pool will take care of spawning the desired number of threads and assigning tasks to them as they become available. Note that even in this case you would still need to loop inside your run() if you want graceful termination (again, see Yoriz
You can also use the killable thread
recipe that basically extends threading.Thread with a method that raises SystemExit exception on the running thread from main. You then enclose your run target with a try/finally and do your cleanup in the finally clause. This results in somewhat neater client code will perform slightly better (as your not checking termination flag on each iteration), but is a bit hacky, imho (it hooks into unexposed functionality -- see the issues on that page). Also this doesn't integrate well with concurrent.futures, so you'll have to write your pooling code as well (if you need it). If you need high-performing killable threads, however, this is the way to go.