前言
Python 多线程是指在一个进程中同时执行多个线程,从而实现并发执行。对于初学者来说,理解起来有难度,我们先来看看怎么用吧,先熟悉,后期在实际中再掌握。
一、创建线程
进程大家都知道,一般打开任务管理器,一个程序对应一个进程,当然也有一个程序对应好几个进程的,线程是比进程更小的单位,比如把抖音看作一个进程,视频播放是一个线程,同时还可以打赏和评论,打赏是一个线程,评论是一个线程。这些线程是可以同时进行的,至少看起来是这样。
在python中,多线程只允许同一时刻只有一个线程在执行,多个线程交替运行,看起来就好像同时在运行一样,这就是并发。下面我们用代码来模拟下:
import threading def test(x,y): for i in range(x,y): print(i) x1 = threading.Thread(name='t1',target=test,args=(0,10)) x2 = threading.Thread(name='t2',target=test,args=(10,20)) x1.start() x2.start()
这里我们需要调用threading模块,通过threading.Thread我们就可以创建线程,这时我们就有x1和x2两个线程了。
二、线程的并发
按照以前的程序运行逻辑,应该是运行完x1,再运行x2,也就是运行结果应该是0到19顺序输出,而实际的输出结果为:
0
1
2
3
410
511
612
713
814
915
16
17
18
19
而且当我再次运行程序时,结果又发生了变化,结果为:
0
1
2
3
4
5
10
11
612
7
8
139
14
15
16
17
18
19
可以看出,程序并不是运行完一个线程在运行另一个,而是随机交叉运行,这就是python的多线程。
三、threading.Thread () 函数
threading.Thread ()里面有很多参数,主要是我们上面所使用的三个,name参数是给线程命名,如果不写,默认为Tread-1,第二个线程就是Tread-2,以此类推。
target参数可以看出来,传进去的是函数名,也就是说是这个线程准备调用的函数。
我们发现args参数的值实际上是传给了test函数,也就是说,args的值传给了线程调用的函数。
以下是一些常用的 threading.Thread() 方法:
- target:指定线程要执行的任务函数。
- args:传递给任务函数的位置参数。
- kwargs:传递给任务函数的关键字参数。
- name:设置线程的名称。
- daemon:设置线程是否为守护线程,如果是守护线程,则主程序退出时会自动销毁该线程。
四、join方法
如果子线程调用join方法,会引起主线程阻塞,通俗来说就是子线程执行完了,才会执行主线程,我们来试一下:
import threading def test(x,y): for i in range(x,y): print(i) x1 = threading.Thread(name='t1',target=test,args=(0,10)) x2 = threading.Thread(name='t2',target=test,args=(10,20)) x1.start() x1.join() x2.start()
我们在启动x1线程后,启动join方法。我们会发现,无论我们重新运行几次代码,输出的结果都是0-19顺序输出,也就是说执行完x1后,再执行x2。
总之,threading.Thread() 的 join() 方法用于阻塞当前线程,直到调用该方法的线程执行完毕。如果不使用 join() 方法等待线程结束,线程的输出结果有可能会出现线程混乱,即第一个线程开启后还没有运行结束,第二个线程已经开启了,可能会出现第二个线程先输出的情况。使用 join() 时,第一个线程的任务完全结束后,才会开启第二个线程,输出的结果也将是有序的 。
五、总结
Python 多线程是指在一个进程中同时执行多个线程,从而实现并发执行。在 Python 中,可以使用 threading
模块来创建和管理线程。以下是一些常用的 threading
模块方法:
Thread()
:创建一个线程对象。start()
:启动线程。join()
:阻塞当前线程,直到调用该方法的线程执行完毕。is_alive()
:判断线程是否还在运行。daemon
:设置线程是否为守护线程,如果是守护线程,则主程序退出时会自动销毁该线程。