1.1 什么是多线程 Threading
同时分批做同一件事情,以提高运算效率
1.2 添加线程 Thread
添加线程
本节我们来学习threading模块的一些基本操作,如获取线程数,添加线程等。首先别忘了导入模块:
import threading
获取已激活的线程数
threading.active_count()
# 2
查看所有线程信息
threading.enumerate()
# [<_MainThread(MainThread, started 140736011932608)>, <Thread(SockThread, started daemon 123145376751616)>]
输出的结果是一个<_MainThread(...)>带多个<Thread(...)>。
查看现在正在运行的线程
threading.current_thread()
# <_MainThread(MainThread, started 140736011932608)>
添加线程,threading.Thread()接收参数target代表这个线程要完成的任务,需自行定义
def thread_job():
print(\'This is a thread of %s\' % threading.current_thread())
def main():
thread = threading.Thread(target=thread_job,) # 定义线程
thread.start() # 让线程开始工作
完整程序与运行结果
import threading
def thread_job():
print(\'This is an added Thread,number is %s\'% threading.current_thread())
def main ():
added_thread=threading.Thread(target=thread_job)
added_thread.start()
print(threading.active_count())
print(threading.enumerate())
print(threading.current_thread())
if __name__==\'__main__\':
main()
\"\"\"
This is an added Thread,number is <Thread(Thread-1, started 6904)>
2
[<_MainThread(MainThread, started 12484)>, <Thread(Thread-1, started 6904)>]
<_MainThread(MainThread, started 12484)>
\"\"\"
1.3 join 功能
- 当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束.
- 当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止。
- 此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止。
- join有一个timeout参数:当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
不加 join() 的结果
我们让T1线程工作的耗时增加.
import threading
import time
def thread_job():
print(\"T1 start\\n\")
for i in range(10):
time.sleep(0.1) # 任务间隔0.1s
print(\"T1 finish\\n\")
added_thread = threading.Thread(target=thread_job, name=\'T1\')
added_thread.start()
print(\"all done\\n\")
```py
预想中输出的结果是否为:
```py
T1 start
T1 finish
all done
```py
但实际却是:
```py
T1 start
all done
T1 finish
```py
## 加入 join() 的结果
线程任务还未完成便输出`all done`。如果要遵循顺序,可以在启动线程后对它调用`join`:
```py
added_thread.start()
added_thread.join()
print(\"all done\\n\")
```py
使用`join`对控制多个线程的执行顺序非常关键。举个例子,假设我们现在再加一个线程`T2`,`T2`的任务量较小,会比`T1`更快完成:
```py
def T1_job():
print(\"T1 start\\n\")
for i in range(10):
time.sleep(0.1)
print(\"T1 finish\\n\")
def T2_job():
print(\"T2 start\\n\")
print(\"T2 finish\\n\")
thread_1 = threading.Thread(target=T1_job, name=\'T1\')
thread_2 = threading.Thread(target=T2_job, name=\'T2\')
thread_1.start() # 开启T1
thread_2.start() # 开启T2
print(\"all done\\n\")
输出的”一种”结果是:
T1 start
T2 start
T2 finish
all done
T1 finish
现在T1和T2都没有join,注意这里说”一种”是因为all done的出现完全取决于两个线程的执行速度, 完全有可能T2 finish出现在all done之后。这种杂乱的执行方式是我们不能忍受的,因此要使用join加以控制。
我们试试在T1启动后,T2启动前加上thread_1.join():
thread_1.start()
thread_1.join() # notice the difference!
thread_2.start()
print(\"all done\\n\")
输出结果:
T1 start
T1 finish
T2 start
all done
T2 finish
可以看到,T2会等待T1结束后才开始运行。
如果我们在T2启动后放上thread_1.join()会怎么样呢?
thread_1.start()
thread_2.start()
thread_1.join() # notice the difference!
print(\"all done\\n\")
``
输出结果:
```py
T1 start
T2 start
T2 finish
T1 finish
all done
T2在T1之后启动,并且因为T2任务量小会在T1之前完成;而T1也因为加了join,all done在它完成后才显示。
你也可以添加thread_2.join()进行尝试,但为了规避不必要的麻烦,推荐如下这种1221的V型排布:
thread_1.start() # start T1
thread_2.start() # start T2
thread_2.join() # join for T2
thread_1.join() # join for T1
print(\"all done\\n\")
\"\"\"
T1 start
T2 start
T2 finish
T1 finish
all done
\"\"\"
1.4 储存进程结果 Queue
1.5 GIL 不一定有效率
1.6 线程锁 Lock
继续阅读与本文标签相同的文章
上一篇 :
工信部拟注销3家企业跨地区增值电信业务经营许可
下一篇 :
应用好广告触摸一体机的小窍门有哪些?
-
将阿里云产品整合成为高校课程实训的训练营产品的实践(二)
2026-05-18栏目: 教程
-
小程序审核常见驳回类型
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 3、join功能
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 4、Queue功能
2026-05-18栏目: 教程
-
Python Threading 学习笔记 | 5、不一定有效率GIL
2026-05-18栏目: 教程
