了解并发之前首先要搞懂两个概念:进程和线程
简单来说:
- 线程是进程的组成部分,一个进程可以有多个线程,一个线程必须有一个父进程。
1、线程的创建和启动
Python提供了两种方式来创建线程:
- 使用threading模块的Thread类的构造器来创建线程
- 继承threading模块的Thread类创建线程类(不推荐)
1.1、使用threading模块的Thread类的构造器来创建线程
import threading
def app(max):
for i in range(max):
# 调用threading模块的current_thread()获取当前线程
# 调用线程对象的getname()获取当前线程的名字
print(threading.current_thread().getName()+ " "+str(i))
for i in range(100):
# 调用threading模块的current_thread()获取当前线程
print(threading.current_thread().getName() + " " + str(i))
if i == 20:
t1 = threading.Thread(target = app,args=(100,))
t1.start()
t2 = threading.Thread(target = app,args=(100,))
t2.start()
print("主线程执行完成")
1.2、继承threading模块的Thread类创建线程类(不推荐)
不推荐使用此方法
2、线程的生命周期
2.1、线程生命周期表
生命周期 | 描述 |
---|---|
新建 | 当程序创建一个thread对象或者thread子类对象时,该线程就处于新建状态。 |
就绪 | 线程对象调用start()之后该程序就处于就绪状态。 |
运行 | 处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,该线程就处于运行状态。 |
阻塞 | 运行中的线程由于各种原因丢失了CPU的使用权,现场就开始处于阻塞状态。 |
死亡 | 程序执行出错或者执行结束,线程死亡。 |
2.2、线程状态转换图
3、控制线程
3.1、 jion()线程
简而言之:join()方法就是让一个线程等待另一个线程完成的方法。
某个流程执行过程中调用其它线程的join方法,调用线程将被阻塞,直到join()方法加入的join线程执行完毕。
import threading
def app(max):
for i in range(max):
print(threading.current_thread().name + "\t" + str(i))
# 启动子线程
threading.Thread(target=app, args=(100,), name="新线程").start()
for i in range(100):
if i == 20:
jt = threading.Thread(target=app, args=(100,), name="被join加入的新线程")
jt.start()
jt.join()
# 主线程调用了线程的join()方法
# 主线程必须等jt线程结束才可以向下执行
print(threading.current_thread().name + "\t" + str(i))
3.2、守护/后台线程
有一种后台运行的线程,专门为其他线程提供服务,我们称之为守护线程或者精灵线程。守护县城有一个很显著的特点,如果所有前台的线程都死亡了,守护现成会自动死亡。
调用Thread对象的daemon可以将指定县城设置为守护线程。
import threading
def app(max):
for i in range(max):
print(threading.current_thread().name + "\t" + str(i))
# 启动子线程
t = threading.Thread(target=app, args=(100,), name="新线程")
# 不设置后台线程,新线程将执行到99
t.daemon = True
# 启动后台线程
t.start()
for i in range(10):
print(threading.current_thread().name + "\t" + str(i))
# 程序执行到此,前台线程结束,后台线程也随之结束。
注意:如果要讲某一个线程设置为为后台线程,设置daemon=True要在调用start()方法之前。
后台线程启动的线程默认为后台线程
3.3、线程睡眠
如果需要让正在执行的线程暂停一段时间(进入阻塞状态),可以调用time模块的sleep(secs)函数来实现,当线程调用sleep()处于阻塞状态后,该线程不会获得执行的机会,直到时间结束。
import threading
import time
for i in range(10):
print("当前时间:\t",time.ctime())
time.sleep(1)