join方法
通过一段代码来直观地展示对全部子线程和子线程列表中最后一个线程调用join方法的差别。
载入库
import threading
import time
用于打印展示的函数
def myprint(value):
for v in value:
print(" value = \t % i "% v)
time.sleep(2)
对于入参中的每个分量,在打印后sleep两秒钟再继续后续打印操作。
values=[1,2,3,4,5,6,7,8,9,10]
threads = []
t1=threading.Thread(target=myprint,args=(values[0:5],))
threads.append(t1)
t2=threading.Thread(target=myprint,args=(values[5:],))
threads.append(t2)
创建一个长度为10的列表,创建名为threads的列表用于存放子线程实例,接下来分别产生两个子线程,target参数是一样的,target函数的参数分别为values的前5个元素和后5个元素。
不使用join方法
start=time.time()
for t in threads:
t.start()
end=time.time()
print("time consume % f " % (end-start))
执行上面代码段得到的输出如下:
value = 1 value = 7
time consume 0.427024
value = 8
value = 2
value = 9
value = 3
value = 4
value = 10
value = 11
value = 5
value = 12 value = 6
可以看出在主线程在两个子线程尚未结束之时便已经执行了。
对线程实例列表中的最后一个线程执行join方法
start=time.time()
for t in threads:
t.start()
t.join()
end=time.time()
print("time consume % f " % (end-start))
这段代码与上一段代码的区别在于t.join()这句,因为其在for循环之外,即只有threads列表中的最后一个会执行该join方法,该代码段执行后的输出结果如下:
value = 1
value = 7
value = 2
value = 8
value = 3
value = 9
value = 4
value = 10
value = 5
value = 11
value = 6
value = 12
time consume 12.036688
从输出的结果可以看出,两个子线程之间并不是顺序执行的,并且主线程是在子线程运行结束后才继续执行的,即子线程结束之前,主线程是被阻塞的。
看到这里,不免有了如果对每个子线程都执行join方法会发生什么的想法,请接着看:
对全部子线程执行join方法
start=time.time()
for t in threads:
t.start()
t.join()
end=time.time()
print("time consume % f " % (end-start))
执行这段代码的结果如下:
value = 1
value = 2
value = 3
value = 4
value = 5
value = 6
value = 7
value = 8
value = 9
value = 10
value = 11
value = 12
time consume 24.004373
与之前的输出做对比可以看出明显的差异,在这段输出中可以看出子线程1和子线程2是顺序执行的,在这种情形下,多线程变得没有意义了。
总结
本文主要对比了不同情形下的join方法起到的作用,加深了对多线程的运行机制的了解。