Stopping a thread after a certain amount of time
I'm looking to terminate some threads after a certain amount of time. These threads will be running an infinite while loop and during this time they can stall for a random, large amount of time. The thread cannot last longer than time set by the duration variable. How can I make it so after the length set by duration, the threads stop.
def main():
t1 = threading.Thread(target=thread1, args=1)
t2 = threading.Thread(target=thread2, args=2)
time开发者_如何转开发.sleep(duration)
#the threads must be terminated after this sleep
This will work if you are not blocking.
If you are planing on doing sleeps, its absolutely imperative that you use the event to do the sleep. If you leverage the event to sleep, if someone tells you to stop while "sleeping" it will wake up. If you use time.sleep()
your thread will only stop after it wakes up.
import threading
import time
duration = 2
def main():
t1_stop = threading.Event()
t1 = threading.Thread(target=thread1, args=(1, t1_stop))
t2_stop = threading.Event()
t2 = threading.Thread(target=thread2, args=(2, t2_stop))
time.sleep(duration)
# stops thread t2
t2_stop.set()
def thread1(arg1, stop_event):
while not stop_event.is_set():
stop_event.wait(timeout=5)
def thread2(arg1, stop_event):
while not stop_event.is_set():
stop_event.wait(timeout=5)
If you want the threads to stop when your program exits (as implied by your example), then make them daemon threads.
If you want your threads to die on command, then you have to do it by hand. There are various methods, but all involve doing a check in your thread's loop to see if it's time to exit (see Nix's example).
If you want to use a class:
from datetime import datetime,timedelta
class MyThread():
def __init__(self, name, timeLimit):
self.name = name
self.timeLimit = timeLimit
def run(self):
# get the start time
startTime = datetime.now()
while True:
# stop if the time limit is reached :
if((datetime.now()-startTime)>self.timeLimit):
break
print('A')
mt = MyThread('aThread',timedelta(microseconds=20000))
mt.run()
An alternative is to use signal.pthread_kill
to send a stop signal. While it's not as robust as @Nix's answer (and I don't think it will work on Windows), it works in cases where Events don't (e.g., stopping a Flask server).
test.py
from signal import pthread_kill, SIGTSTP
from threading import Thread
import time
DURATION = 5
def thread1(arg):
while True:
print(f"processing {arg} from thread1...")
time.sleep(1)
def thread2(arg):
while True:
print(f"processing {arg} from thread2...")
time.sleep(1)
if __name__ == "__main__":
t1 = Thread(target=thread1, args=(1,))
t2 = Thread(target=thread2, args=(2,))
t1.start()
t2.start()
time.sleep(DURATION)
# stops all threads
pthread_kill(t2.ident, SIGTSTP)
result
$ python test.py
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
[19]+ Stopped python test.py
精彩评论