Hellosiroverthere
Hellosiroverthere

Reputation: 315

Python - Making threading.thread not to wait for other threads to be done and to loop forever

So I am trying to figure out how threading more and more and I just made a simple script that looks like:

def test(name):
    while True:
          print(name)
          time.sleep(1)   



def main():
    try:
        random_names = []
        for names in [line.rstrip('\n') for line in open('name.txt')]:
            random_names.append(names)

        threads = []
        for name in random_names:
            p = threading.Thread(target=test, args=(name,))
            threads.append(p)
            p.start()

        for thread in threads:
            thread.join()

    except KeyboardInterrupt:
        print('Keyboard - Interrupted')
        sys.exit()

Basically I just created random text file that contains 100 names (Totally random) where my goal are that each thread will have a given thread running for it.

Now there is something I quite didn't get a grip off. I assume using thread.join is that when there is 100 threads running. Whenever 1 of them are done, it will wait basically until the rest are done if I am correct?

That takes me to question two: If you don't want it to happend and you basically just want to run the threading "for itself" meaning that whenever one of the thread is done, instead of waiting it should just continue to work again instead of waiting for the rest of threads to run?

And to my final question is, in which way would it possible to make it so the threads are running forever in that case? I assume that this code I am using now might be the fix now since I am using a while True: but is that a valid thing to do and will that mean that the thread.join will not even be touched if there is a while True running over and over in the def test()?

Upvotes: 1

Views: 2216

Answers (1)

Gil Hamilton
Gil Hamilton

Reputation: 12357

Each thread will run completely independent of the others (except as you create interdependencies). So if you create 100 threads, and the threads don't need any interaction from other threads, and one of them completes (i.e. exits by returning from its target function), the other 99 are unaffected and will just continue to run.

thread.join causes the calling thread to wait until the single target thread completes. In the absence of a timeout or some other outside factor, it will wait forever for the target thread to complete. The join is unaffected by any thread other than the target thread. In other words, if you're attempting to join thread 1, and thread 2 quits, that will not cause your join of thread 1 to complete any sooner or later.

In your code, your threads are all executing a while True, which means none of them will ever return from their target function and hence will never "complete". That means your main thread will hang on the first thread.join call forever. It's perfectly valid for your 100 threads to all execute forever if that is what you wish.

Likewise, it's fine for your main thread to call join like that. But of course, the main thread could go on to do other work as well. And if you don't expect the other threads to exit, there's no requirement for the main thread to call join. It could simply return (in effect, completing itself). The other threads and your program itself will happily continue to execute.

Or, you could even create 99 additional threads and have the main thread join in and call your test function as the 100th. (This would of course complicate the logic of your clean read-a-line-start-a-thread loop so I wouldn't actually recommend that.)

The way you have it now seems ideal. Because you are having the main thread wait in the join (even though the join will never complete), your KeyboardInterrupt exception handler remains in scope in the main thread so that your program terminates cleanly on Ctrl-C (sys.exit kills the entire process, and hence all the threads are terminated).

EDIT:
Apparently, sys.exit does not terminate the entire process -- only the thread in which it executes. You would need to use os._exit from the KeyboardInterrupt handler to exit cleanly (or stop each of the threads first).

Upvotes: 1

Related Questions