最近因为工作需求,需对代码运行加上计时器,1小时后,无论代码是否运行结束都得重新执行代码。为满足需求,需开启多线程两个线程,分别运行主程序,计时器。
如果程序运行到一半所用的时间到达1小时,需杀死当前线程重新运行,或者程序运行结束后,计时器还未到达1小时,也需杀死计时器线程程序结束运行。
杀死线程的方法
def _async_raise(tid, exctype):
"""杀死线程"""
"""raises the exception, performs cleanup if needed"""
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def stop_thread(thread):
_async_raise(thread.ident, SystemExit)
重写多线程封装主程序
class MainThread(threading.Thread):
def __init__(self, q, main, *arg, **kwargs):
super(MainThread, self).__init__()
self.main = main
self.q = q
self.arg = arg
self.kwargs = kwargs
def run(self):
self.main(*self.arg, **self.kwargs)
self.q.put("main")
重写多线程封装计时器
class TimerThread(threading.Thread):
def __init__(self, q, sleep):
super(TimerThread, self).__init__()
self.sleep = sleep
self.q = q
def run(self):
i = 0
while i != self.sleep:
i += 1
time.sleep(1)
self.q.put("timer")
重写多线程,使用 queue 进行线程之间的通信,判断子线程是否结束,如果结束,强制杀死另一个子线程。
class Controller(threading.Thread):
def __init__(self, q, timer_arg, main, *main_arg, **main_kwargs):
threading.Thread.__init__(self)
self.q = q
# 计时器
self.timer_arg = timer_arg
# 主流程
self.main = main
self.main_arg = main_arg
self.main_kwargs = main_kwargs
self.threadList = [TimerThread(self.q,self.timer_arg),
MainThread(self.q, self.main, *self.main_arg, **self.main_kwargs)]
def run(self):
for each in self.threadList:
each.start()
while True:
q_value = self.q.get()
if q_value == "timer":
self.threadList[0] = TimerThread(self.q,self.timer_arg)
self.threadList[0].start()
if self.threadList[1].is_alive():
stop_thread(self.threadList[1])
self.threadList[1] = MainThread(self.q, self.main, *self.main_arg, **self.main_kwargs)
self.threadList[1].start()
continue
else:
break
if q_value == "main":
stop_thread(self.threadList[0])
break
运行程序
def main(*arg, **kwargs):
print(*arg)
time.sleep(5)
if __name__ == '__main__':
for i in range(3):
q = queue.Queue()
c = Controller(q, 3600, main, "xx:{}".format(i))
c.start()
c.join()