ished I sleep 2 seconds
Thread-3 finished I sleep 2 seconds
Thread-5 finished I sleep 3 seconds
# 其实是在线程5,也就是最后一个线程出阻塞的
main thread finished.
cost: 3.001293659210205
Thread-2 finished I sleep 4 seconds
Thread-4 finished I sleep 5 seconds
正确的方法,定义一个空列表,获取所以的线程实例,for 循环阻塞所有的线程实例
# -*- coding: UTF-8 -*-
import threading
import time
import random
class MyThread(threading.Thread):
def __init__(self, n):
super(MyThread, self).__init__()
self.n = n
def run(self):
print('task %s is operating' % self.n)
t_time = random.randint(1, 8)
time.sleep(t_time)
print(self.getName(), 'finished', 'I sleep %d seconds' % t_time)
if __name__ == '__main__':
t_list = []
start_time = time.time()
for i in range(5):
t = MyThread(i)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print('main thread finished.')
print('cost: %s' % (time.time() - start_time))
结果,事实上也符合我们刚才的推论,运行时间最长的线程所消耗的时间,就是总的并发时间
task 0 is operating
task 1 is operating
task 2 is operating
task 3 is operating
task 4 is operating
Thread-3 finished I sleep 3 seconds
Thread-5 finished I sleep 3 seconds
Thread-2 finished I sleep 7 seconds
Thread-1 finished I sleep 7 seconds
Thread-4 finished I sleep 8 seconds
main thread finished.
cost: 8.001787185668945
# 并发时间在8秒左右
总结:主线程创建一个子线程后,如果子线程调用join()方法,主线程会在调用的地方等待,直到该子线程运行完成才会接着往下执行。
三、守护线程setDaemon
setDaemon()方法:在主线程中创建子线程,该子线程调用setDaemon方法后成为主线程的守护线程。这种情况下如果主线程执行结束,那么不管子线程是否完成,一并和主线程退出。这里基本和join()方法相反。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起。
# -*- coding: UTF-8 -*-
import threading
import time
import random
class MyThread(threading.Thread):
def __init__(self, n):
super(MyThread, self).__init__()
self.n = n
def run(self):
print('task %s is operating' % self.n)
t_time = random.randint(1, 8)
time.sleep(t_time)
print(self.getName(), 'finished', 'I sleep %d seconds' % t_time)
if __name__ == '__main__':
start_time = time.time()
for i in range(5):
t = MyThread(i)
t.setDaemon(True)
t.start()
print('main thread finished.', threading.current_thread(), threading.active_count())
print('cost: %s' % (time.time() - start_time))
注:threading.current_thread()查看当前运行的线程
threading.active_count() 查看活跃线程数
线程数 = 主线程 + 子线程数
结果:
task 0 is operating
task 1 is operating
task 2 is operating
task 3 is operating
task 4 is operating
main thread finished. <_MainThread(MainThread, started 8656)> 6
cost: 0.0009999275207519531
Process finished with exit code 0
# 很显然把子线程设置为主线程的守护线程后,主线程一旦结束,程序就执行退出运行,不会再等待子线程运行。
注:如果程序中有其他非守护线程时,还是会等待非守护线程运行完毕,程序才会结束。