Home > Back-end >  How can I make each Thread to join in python?
How can I make each Thread to join in python?

Time:11-16

Let me describe an example:

import time
import threading

def some_heavy_function():
    pass

while True:
    t1 = threading.Thread(target=some_heavy_function, args=(,))
    t2 = threading.Thread(target=some_heavy_function, args=(,))
    t3 = threading.Thread(target=some_heavy_function, args=(,))

    t1.start()
    t2.start()
    t3.start()

    time.sleep(10)

What I want is, 1) I don't want each thread to work again every 10 seconds.
Each function will take more than 10 seconds, so I don't want each function to be invoked again.
So I need to use .join().

But, 2) I want each function to be invoked again every 10 seconds if is not currently working.
In some situation, let's say t3 would not be invoked in the first place. But it should be invoked after 10 seconds even while t1 or t2 is working.

So when you read the 1) above, you may suggest me to put

t1.join()
t2.join()
t3.join()

after three .start()s and before time.sleep(10),
but this makes t3 to wait until t1 and t2 finish their jobs, so that t3 is not invoked even after 10 seconds.

Of course, putting each of .join() method after each .start() method would not let me to enjoy multi-thread.

Help!

CodePudding user response:

You need some kind of control structure (a dictionary is ideal) wherein you can monitor the state of your threads.

For each thread you need to make a note of when it started. In that way you can determine how long it's been running.

You can use Thread.is_alive() to determine the state of your threads.

Here, the "heavy" function is actually a sleep for a random amount of time.

By printing the thread id (of our own making), the duration of its sleep and the actual time you can prove that this satisfies the criteria.

This code will need to be adapted in some way because, as it stands, it will run forever.

from threading import Thread
from random import randint
from time import sleep, time

def some_heavy_function(tid):
    ri = randint(1, 15)
    print(f'{tid} starting. Will sleep for {ri}s. Time={int(time())}')
    sleep(ri)
    print(f'{tid} ending')

NTHREADS = 3
TIME = 10
# tp is the thread reference
# st is the time that the thread was started
control = {f't{n}': {'tp': None,  'st': 0} for n in range(NTHREADS)}

while True:
    for k, v in control.items():
        if v['tp'] is not None and not v['tp'].is_alive():
            v['tp'].join()
            v['tp'] = None
        if v['tp'] is None and time() - v['st'] > TIME:
            v['tp'] = Thread(target=some_heavy_function, args=(k,))
            v['st'] = time()
            v['tp'].start()
    sleep(1)

CodePudding user response:

Do you really need to join at all? It looks like you are checking every 10 seconds for dead threads, and want to restart them. Wouldn't this do?:

import time
import threading

def some_heavy_function():
    pass

t1 = threading.Thread(target=some_heavy_function, args=(,))
t2 = threading.Thread(target=some_heavy_function, args=(,))
t3 = threading.Thread(target=some_heavy_function, args=(,))

t1.start()
t2.start()
t3.start()

while True:
    time.sleep(10)
    for t in [t1,t2,t3]:
        if not t.is_alive():
            t.start()
  • Related