在 Python 的多线程编程中,经常碰到 thread.join()这样的代码。那么今天咱们用实际代码来解释一下 join 函数的作用。
第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束,例子见下面。
# coding: utf-8 # 测试多线程中join的功能 import threading, time def doWaiting(): print 'start waiting1: ' + time.strftime('%H:%M:%S') + " " time.sleep(3) print 'stop waiting1: ' + time.strftime('%H:%M:%S') + " " def doWaiting1(): print 'start waiting2: ' + time.strftime('%H:%M:%S') + " " time.sleep(8) print 'stop waiting2: ', time.strftime('%H:%M:%S') + " " tsk = [] thread1 = threading.Thread(target = doWaiting) thread1.start() tsk.append(thread1) thread2 = threading.Thread(target = doWaiting1) thread2.start() tsk.append(thread2) print 'start join: ' + time.strftime('%H:%M:%S') + " " print 'end join: ' + time.strftime('%H:%M:%S') + " "
代码执行结果如下:
start waiting1: 22:24:20 start join: 22:24:20 start waiting2: 22:24:20 end join: 22:24:20 stop waiting1: 22:24:23 stop waiting2: 22:24:28
第二,当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例子见下面。
1 # coding: utf-8 2 # 测试多线程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + " " 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + " " 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + " " 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + " " 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.setDaemon(True) 15 thread1.start() 16 tsk.append(thread1) 17 thread2 = threading.Thread(target = doWaiting1) 18 thread2.setDaemon(True) 19 thread2.start() 20 tsk.append(thread2) 21 print 'start join: ' + time.strftime('%H:%M:%S') + " " 22 23 print 'end join: ' + time.strftime('%H:%M:%S') + " "
代码执行结果如下:
start waiting1: 22:34:46 start waiting2: 22:34:46 start join: 22:34:46 end join: 22:34:46
第三,没有设置守护线程且没有设置join函数的timeout参数时,主线程将会一直等待,直到子线程全部结束,主线程才结束,程序退出。代码如下:
1 # coding: utf-8 2 # 测试多线程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + " " 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + " " 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + " " 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + " " 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.start() 15 tsk.append(thread1) 16 thread2 = threading.Thread(target = doWaiting1) 17 thread2.start() 18 tsk.append(thread2) 19 print 'start join: ' + time.strftime('%H:%M:%S') + " " 20 for tt in tsk: 21 tt.join() 22 print 'end join: ' + time.strftime('%H:%M:%S') + " "
代码执行结果如下:
start waiting1: 22:41:50 start join: 22:41:50 start waiting2: 22:41:50 stop waiting1: 22:41:53 stop waiting2: 22:41:58 end join: 22:41:58
第四,当没有设置守护线程且join函数的参数timeout=2时,主线程将会等待多个子线程timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。代码如下:
1 # coding: utf-8 2 # 测试多线程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + " " 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + " " 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + " " 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + " " 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.start() 15 tsk.append(thread1) 16 thread2 = threading.Thread(target = doWaiting1) 17 thread2.start() 18 tsk.append(thread2) 19 print 'start join: ' + time.strftime('%H:%M:%S') + " " 20 for tt in tsk: 21 tt.join(2) 22 print 'end join: ' + time.strftime('%H:%M:%S') + " "
代码执行结果如下:
start waiting1: 23:02:34 start waiting2: 23:02:34 start join: 23:02:34 stop waiting1: 23:02:37 end join: 23:02:38 stop waiting2: 23:02:42
第五,当设置守护线程join函数的参数timeout=2时,主线程将会等待多个子线程timeout的累加和这样的一段时间,时间一到,主线程结束,杀死未执行完的子线程,程序退出。代码如下:
1 # coding: utf-8 2 # 测试多线程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + " " 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + " " 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + " " 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + " " 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.setDaemon(True) 15 thread1.start() 16 tsk.append(thread1) 17 thread2 = threading.Thread(target = doWaiting1) 18 thread2.setDaemon(True) 19 thread2.start() 20 tsk.append(thread2) 21 print 'start join: ' + time.strftime('%H:%M:%S') + " " 22 for tt in tsk: 23 tt.join(2) 24 print 'end join: ' + time.strftime('%H:%M:%S') + " "
代码执行结果如下:
start waiting1: 23:23:57 start waiting2: 23:23:57 start join: 23:23:57 stop waiting1: 23:24:00 end join: 23:24:01