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()