Python多线程之join()用法
2021/10/12 12:44:14
本文主要是介绍Python多线程之join()用法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
知识点:进程是分配资源的单位,线程是运算调度的单位。进程相当于资源,线程相当于控制流。
当一个进程建立时,就会有一个主线程。
进程当中的资源,如果只有一个线程在消耗,那无疑会余下空闲资源被浪费,此时就需要多线程去协同调度进程内的资源。
知识点:守护线程会随着主线程结束而结束,守护进程会随着主进程结束而结束。
例如 QQ关闭时,聊天窗口一并关闭。QQ是进程,聊天窗口也是进程,不过是主进程与子进程(守护进程)的关系。
setDaemon():设置守护线程
threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None) 参数列表中target是指定执行的任务,args是传参
Thread 的生命周期
- 创建对象时,代表 Thread 内部被初始化。
- 调用 start() 方法后,thread 会开始运行。
- thread 代码正常运行结束或者是遇到异常,线程会终止。
start()方法让线程进入runnable队列,具体什么时候执行,由cpu决定
join()是阻塞,将当前子线程阻塞,主线程要等待一段时间后才能继续执行。
一、setDaemon(False) 即系统默认情况下的设置
程序代码:
import threading import time def run(): """ : 每个线程的任务都是run : thread.current_thread().name:当前线程名称 :return: None """ son_start_time = time.time() for i in range(1, 6): print(f"[线程 {threading.current_thread().name} 现在执行到了{i}]") time.sleep(1) print(f"[子线程{threading.current_thread().name}结束,耗时:{time.time() - son_start_time}]") if __name__ == '__main__': start_time = time.time() # 用于装线程的列表 thread_list = [] # 依次新建 5 个 线程 for i in range(5): thread_list.append(threading.Thread(target=run)) # 多个线程依次设置 非 守护线程,并执行 for i in thread_list: i.setDaemon(False) i.start() # 主线程等待三秒 time.sleep(3) print(f"[主线程{threading.current_thread().name}结束啦 ! 耗时:{time.time() - start_time}] ")
结果如图:
如上图所示,主线程在执行完自己的任务后便结束,子线程继续执行自己的任务。
当前是子线程无返回值的情况,主线程和子线程相关性并不大,那么子线程若是需要返回结果给主线程,其执行情况又是怎样呢?
实现过程如下:
""" title:多线程——join试验 author:阿松不飞 """ import threading import time from queue import Queue def run(q): """ : 每个线程的任务都是run : thread.current_thread().name:当前线程名称 :return: res """ son_start_time = time.time() for i in range(1, 6): print(f"[线程 {threading.current_thread().name} 现在执行到了{i}]") time.sleep(1) # q 调用put方法把将要返回的结果放入队列 q.put(f"[子线程{threading.current_thread().name}结束,耗时:{time.time() - son_start_time}]") if __name__ == '__main__': start_time = time.time() # 用于装线程的列表 thread_list = [] # 新建一个队列,用来装取结果 q = Queue() # 依次新建 5 个 线程 for i in range(5): # 将队列 q 传入线程方法当中 thread_list.append(threading.Thread(target=run, args=(q,))) # 多个线程依次设置 非 守护线程,并执行 for i in thread_list: i.setDaemon(False) i.start() # 依次取出 q 队列中的结果 for i in range(5): print(q.get()) # 主线程等待三秒 time.sleep(3) print(f"[主线程{threading.current_thread().name}结束啦 ! 耗时:{time.time() - start_time}] ")
这个是队列存取结果的方案,因为我测试了 在run方法中放入return,然后主线程通过i.start() 获得返回值,结果总是None,便要换种获取结果的方案。
队列方案的运行结果如下:
那么由此可以看到,因为要获取到子线程的返回值,所以主线程的执行过程中,会有一个等待q队列的过程,而q队列会在等待子线程。
二、setDaemon(True)
当setDaemon为true时,被设置的线程会成为主线程的守护线程。
主线程若是结束,则会连带守护线程一起结束,守护线程不再执行,但是其余非守护线程还可以执行。
示例代码如下:
import threading import time def run(): """ : 每个线程的任务都是run : thread.current_thread().name:当前线程名称 :return: res """ son_start_time = time.time() for i in range(1, 6): print(f"[线程 {threading.current_thread().name} 现在执行到了{i}]") time.sleep(1) print(f"[子线程{threading.current_thread().name}结束,耗时:{time.time() - son_start_time}]") if __name__ == '__main__': start_time = time.time() # 用于装线程的列表 thread_list = [] # 依次新建 5 个 线程 for i in range(5): thread_list.append(threading.Thread(target=run)) # 多个线程依次设置 非 守护线程,并执行 for i in thread_list: i.setDaemon(True) i.start() # 主线程等待三秒 time.sleep(3) print(f"[主线程{threading.current_thread().name}结束啦 ! 耗时:{time.time() - start_time}] ")
其结果如图:
可以看到,当我设置了这些线程为守护线程之后, 主线程一旦执行完毕,守护线程随着主线程关闭
那么接来下测试线程中join的作用
运行代码:
import threading import time def run(): """ : 每个线程的任务都是run : thread.current_thread().name:当前线程名称 :return: res """ son_start_time = time.time() for i in range(1, 6): print(f"[线程 {threading.current_thread().name} 现在执行到了{i}]") time.sleep(1) print(f"[子线程{threading.current_thread().name}结束,耗时:{time.time() - son_start_time}]") if __name__ == '__main__': start_time = time.time() # 用于装线程的列表 thread_list = [] # 依次新建 5 个 线程 for i in range(5): thread_list.append(threading.Thread(target=run)) # 多个线程依次设置 非 守护线程,并执行 for i in thread_list: i.setDaemon(True) i.start() for i in thread_list: i.join() # 主线程等待三秒 time.sleep(3) print(f"[主线程{threading.current_thread().name}结束啦 ! 耗时:{time.time() - start_time}] ")
其运行结果如下:
当守护线程用上join方法的时候,join之中会有一个默认的timeout参数,在子线程执行过程中将阻塞主线程,让主线程去等待自己,等待的时长最大为timeout的时长,最短为子线程执行结束时间(<timeout时)。一旦等待超时,主线程不再等待,继续往下执行,当主线程执行结束,子线程也被关闭。
测试代码:
""" title:多线程——join试验 author:阿松不飞 """ import threading import time def run(): """ : 每个线程的任务都是run : thread.current_thread().name:当前线程名称 :return: res """ son_start_time = time.time() for i in range(1, 6): print(f"[线程 {threading.current_thread().name} 现在执行到了{i}]") time.sleep(1) print(f"[子线程{threading.current_thread().name}结束,耗时:{time.time() - son_start_time}]") if __name__ == '__main__': start_time = time.time() # 用于装线程的列表 thread_list = [] # 依次新建 5 个 线程 for i in range(5): thread_list.append(threading.Thread(target=run)) # 多个线程依次设置 非 守护线程,并执行 for i in thread_list: i.setDaemon(True) i.start() for i in thread_list: i.join(timeout=0.1) print(f"[主线程{threading.current_thread().name}结束啦 ! 耗时:{time.time() - start_time}] ")
执行结果:
这篇关于Python多线程之join()用法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门
- 2024-11-14Python编程入门指南
- 2024-11-13Python基础教程
- 2024-11-12Python编程基础指南
- 2024-11-12Python基础编程教程
- 2024-11-08Python编程基础与实践示例
- 2024-11-07Python编程基础指南
- 2024-11-06Python编程基础入门指南
- 2024-11-06怎么使用python 计算两个GPS的距离功能-icode9专业技术文章分享