python 的多线程机制可以的适用场景不适合与计算密集型的,因为 GIL 的存在,多线程在处理计算密集型时,实际上也是串行的,因为每个时刻只有一个线程可以获得 GIL,但是对于 IO 处理来说,不管是网络IO还是文件读写IO还是数据库IO,由于从用户态切换到内核态时,此时线程就陷入等待,线程让出对应 CPU,此时就可以切换到其他线程上继续执行任务,总的来说, python 的多线程机制适用于处理 IO 密集型任务。
这里引申出多线程机制的相关应用,python 的标准库中已经为我们提供了 threading模块,我们可以根据其中的 Thread类 进行线程的相关处理,主要就是创建,运行,阻塞,判断是否存活等操作:
- Thread(target=func, args=(), name=“myname”)
- Thread.is_alive()
- Thread.start()
- Thread.join()
但 python 的标准库的线程类仅提供了些简单操作,更多的线程控制,实际上并没有,比如针对超时或者对正在运行的线程停掉等,而且只要子线程 start() 后,其运行就脱离控制了,即使 join(timeout=10) 设置,也只是针对 is_alive() 进行属性的更改,这一点 golang 就在 goroutine 中做得很好,这里不是讨论重点。
接下来,我们就来看看线程类的使用吧。
1.start()后立即join()操作
很多刚使用 python 的人可能在 start() 后就立即 join(),这里会有问题,具体怎样呢,我们看看示例:
import time, datetime
import threading
import sys
def foo(sleep=2):
print("当前thread: [{}]".format(threading.current_thread().name))
time.sleep(sleep)
print("thread: [{}] end.".format(threading.current_thread().name))
def multiThread_v1():
"""
version1: 多个线程start后再join
:return:
"""
print("[{}] [{}] start...".format(datetime.datetime.now(), sys._getframe().f_code.co_name))
t1 = threading.Thread(target=foo, name="t1"