Search code examples
pythonpython-3.xmultithreadingoperating-systempython-multithreading

How to continue the program flow after one of several threads returns a value?


In my program, there is a section where I utilize from multiple threads for simulating a distributed environment. All threads are trying to crack a password. As you can see, all threads call the same target function func with different arguments. This function returns a result whenever a trial that cracks the password is found.

def func(self, inp):
    trial = 0
    while (crackPwd(inp, trial) != True):
        trial += 1
    return inp

threads = []

for inp in range(inpAmount):
    thr = threading.Thread(target=func, args=(inp))
    threads.append(thr)
    thr.start()

for thr in threads:
    thr.join()

However what I want to do is to stop other threads after one of the threads cracks the password. I mean, I want to continue with the program flow after a thread returns a result from func(). I tried to find a solution but none of them seems to match my problem. Now, I got results from all threads and lose so much time waiting for all threads to finish. I will appreciate your help.


Solution

  • Could you use an instance of the threading Event class?

    By mocking the crackPwd function mentioned in your code to sleep until the sleep_time is 10 seconds (with 10% probability) I tested with:

    import time
    import random
    import threading
    
    def crackPwd(inp, trial):
       sleep_time = random.randint(1, 10)
       time.sleep(sleep_time)
       return sleep_time
    
    def func(inp):
       trial = 0
       while (crackPwd(inp, trial) != 10) and (not pwd_cracked.isSet()):
          trial += 1
       pwd_cracked.set()
       return inp
    
    threads = []
    
    for inp in range(10):
       pwd_cracked = threading.Event()
       thr = threading.Thread(target=func, args=(inp, ))
       threads.append(thr)
       thr.start()
    
    for thr in threads:
       thr.join()
    

    So for your original code:

    def func(self, inp):
        trial = 0
        while (crackPwd(inp, trial) != True) and (not pwd_cracked.isSet()):
            trial += 1
        pwd_cracked.set()
        return inp
    
    threads = []
    
    for inp in range(inpAmount):
        pwd_cracked = threading.Event()
        thr = threading.Thread(target=func, args=(inp, ))
        threads.append(thr)
        thr.start()
    
    for thr in threads:
        thr.join()