ps:这篇能解决简单的线程问题,但是我遇到了问题,由于我开了多个线程,线程里面还有死循环,导致的结果就是销毁线程后,死循环仍在运行。于是我在这篇的基础上又写了一篇进阶篇,来解决这个问题。
主要解决创建线程如何带参数,以及主进程对线程的销毁问题。
之前使用的_thread库不支持销毁,必须使用threading库。
实现效果:主线程打印’222‘,子线程每隔1s打印’111‘,延迟10s,关闭子进程
介绍两种方法,第一种简单粗暴,代码如下:
import threading,time
def stop_thread(thread):
import inspect
import ctypes
tid = thread.ident
exctype = SystemExit
"""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:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def serial_read(delay):
while(1):
time.sleep(delay)
print('111')
pass
try:
myThread = threading.Thread(target=serial_read,args=(1,))
myThread.start()
except:
print('error')
print('222')
time.sleep(10)
stop_thread(myThread)
这里重点介绍一下第二种方法,某些时候第一种方法不适用,会报错。例如开了一个线程,在线程内部又开了一个线程,此时关闭第一个线程就会报如下错误。
raise ValueError("invalid thread id")
ValueError: invalid thread id
相比而言第2种更安全一些,
方法2代码如下:
# encoding:utf-8
import time
import threading
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self, *args, **kwargs):
super(StoppableThread, self).__init__(*args, **kwargs)
self._stop_event = threading.Event()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
def run(self):
print("begin run the child thread")
while True:
print("sleep 1s")
time.sleep(1)
if self.stopped():
# 做一些必要的收尾工作
break
if __name__ == "__main__":
print("begin run main thread")
t = StoppableThread()
t.start()
time.sleep(3)
t.stop()
print("main thread end")