Daemon thread
The threading module supports daemon threads, and its working method is: daemon threads are generally a server waiting for clients to request services. If there is no client request, the daemon thread is idle. If a thread is set as a daemon thread, it means that this thread is not important, and there is no need to wait for the execution of this thread to complete when the process exits.
Set the thread as a daemon thread:
thread.daemon = True
Check the guardian status of the thread, just check this value.
The entire python program will exit after all non-daemon threads exit, that is, the daemon thread guarantees the normal operation of other non-daemon threads.
Create thread
Use Thread to create a thread (recommended to choose the first three):
- Create an instance of Thread and pass it a function.
- Create an instance of Thread and pass it a callable class instance.
- Derive a subclass of Thread and create an instance of the subclass.
Create an instance of Thread and pass it a function
Code
import threading
from time import sleep,ctime
loops = [4,2]
def loop(nloop,nsec):
print('start loop ',nloop,' at:',ctime())
sleep(nsec)
print('loop ',nloop,' done at:',ctime())
def main():
print('starting at:',ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(target=loop,args=(i,loops[i])) # 实例化Thread
# loop为目标函数名,args为目标函数参数
threads.append(t)
for i in nloops: # 开始线程
threads[i].start()
for i in nloops: # 等待所有
threads[i].join() # 线程完成
print('all DONE at:',ctime())
if __name__ == "__main__":
main()
Output
starting at: Thu Sep 10 16:18:48 2020
start loop 0 at: Thu Sep 10 16:18:48 2020
start loop 1 at: Thu Sep 10 16:18:48 2020
loop 1 done at: Thu Sep 10 16:18:50 2020
loop 0 done at: Thu Sep 10 16:18:52 2020
all DONE at: Thu Sep 10 16:18:52 2020
join()
The method will wait for the thread to end, or if the timeout period is provided, the timeout period is reached. The join()
method of use is clearer than the infinite loop waiting for the lock to be released (this kind of lock is also known as the reason for the spin lock).如果主线程还有其他事情要去做,而不是等待这些线程完成(例如其他处理或者等待新的客户端请求),就可以不调用join()。join()方法只有在你需要等待线程完成的时候才是有用的。
Create an instance of Thread and pass it a callable class instance
Code
import threading
from time import sleep,ctime
loops = [4,2]
class ThreadFunc(object):
def __init__(self,func,args,name=''):
self.name = name
self.func = func
self.args = args
def __call__(self):
self.func(*self.args)
def loop(nloop,nsec):
print('start loop ',nloop,' at:',ctime())
sleep(nsec)
print('loop ',nloop,' done at:',ctime())
def main():
print('starting at:',ctime())
threads = []
nloops = range(len(loops))
for i in nloops: # 创建所有线程
t = threading.Thread(
target=ThreadFunc(loop,(i,loops[i]),
loop.__name__))
threads.append(t)
for i in nloops: # 开始所有线程
threads[i].start()
for i in nloops: # 等待完成
threads[i].join()
print('all DONE at:',ctime())
if __name__ == "__main__":
main()
Output
starting at: Thu Sep 10 16:43:57 2020
start loop 0 at: Thu Sep 10 16:43:57 2020
start loop 1 at: Thu Sep 10 16:43:57 2020
loop 1 done at: Thu Sep 10 16:43:59 2020
loop 0 done at: Thu Sep 10 16:44:01 2020
all DONE at: Thu Sep 10 16:44:01 2020
When instantiating the Thread object, the callable class ThreadFunc is also instantiated. At the same time, this class saves the function parameter args, the function itself func, and the string name of the function name. When a new thread is created, the code of the Thread class will call the ThreadFunc object, and then call the __call__() method (the function of this method is similar to overloading the () operator in the class, so that the class instance object can be called like ordinary Like functions, it is used in the form of "object name ()"). `Since we already have the parameters to be used, there is no need to pass them to the Thread() constructor, just call them directly.
Derive a subclass of Thread and create an instance of the subclass
Code
import threading
from time import sleep,ctime
loops = (4,2)
class MyThread(threading.Thread):
def __init__(self,func,args,name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
def run(self):
self.func(*self.args)
def loop(nloop,nsec):
print('start loop ',nloop,' at:',ctime())
sleep(nsec)
print('loop ',nloop,' done at:',ctime())
def main():
print('starting at:',ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = MyThread(loop,(i,loops[i]),loop.__name__)
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print('all DONE at:',ctime())
if __name__ == '__main__':
main()
Output
starting at: Thu Sep 10 17:18:35 2020
start loop 0 at: Thu Sep 10 17:18:35 2020
start loop 1 at: Thu Sep 10 17:18:35 2020
loop 1 done at: Thu Sep 10 17:18:37 2020
loop 0 done at: Thu Sep 10 17:18:39 2020
all DONE at: Thu Sep 10 17:18:39 2020
Compared 创建Thread的实例,传给它一个可调用的类实例
with the derived subclasses, there are two changes:
- The constructor of the MyThread subclass must first call the constructor of its base class;
- The previous special method __call__() must be written as run() in this subclass