一、线程创建步骤
1、导入线程模块
import threading
2、通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)
3、启动线程执行任务
线程对象.start()
其中第二步和多进程创建进程对象不同的是传参的参数名有两个不同,其中target是相同的,指的是函数名或者方法名。name指的是线程名,可以给线程起个名字,一般不用设置,系统会自己取。group指的是线程组。
看代码示例
import threading
import time
def eat():
for i in range(4):
print("我吃……")
time.sleep(0.5)
def drink():
for i in range(4):
print("我喝……")
time.sleep(0.5)
if __name__ == '__main__':
eat_thread = threading.Thread(target=eat)
drink_thread = threading.Thread(target=drink)
eat_thread.start()
drink_thread.start()
运行结果如图
二、线程执行带有参数的任务
此处和多线程一样,两种方式,分别是元组args和字典kwargs。
args使用方式
eat_thread = threading.Thread(target=eat,args=("giao",))
此处要注意的是,args如果只有一个元素,后面的逗号不能省略!
kwargs使用方式
drink_thread = threading.Thread(target=drink,kwargs={"name":"qz"})
看代码示例:
import threading
import time
def eat(name):
for i in range(4):
print(name+"我吃……")
time.sleep(0.5)
def drink(name,count):
for i in range(count):
print(name+"我喝……")
time.sleep(0.5)
if __name__ == '__main__':
eat_thread = threading.Thread(target=eat,args=("giao",))
drink_thread = threading.Thread(target=drink,kwargs={"name":"qz","count":5})
eat_thread.start()
drink_thread.start()
运行结果如图
三、主线程和子线程的结束顺序
首先说进程,主进程会等待所有子进程执行结束后再结束
线程也是类似的,主线程会等待所有的子线程执行结束之后再结束
看代码示例:
import threading
import time
def eat(name):
for i in range(4):
print(name+"我吃……")
time.sleep(0.5)
def drink(name,count):
for i in range(count):
print(name+"我喝……")
time.sleep(0.5)
if __name__ == '__main__':
eat_thread = threading.Thread(target=eat,args=("giao",))
drink_thread = threading.Thread(target=drink,kwargs={"name":"qz","count":4})
eat_thread.start()
drink_thread.start()
time.sleep(1)
print("我吃不下也喝不下了!")
运行结果如图:
可以清楚的看到,主线程已经结束之后,子线程依旧在运行
四、设置守护主线程
如果我们想让主线程结束之后,子线程也随即结束,那么我们可以使用线程守护
我们可以使用daemon,这个单词意思
- daemon
- n.(古希腊神话中的)半神半人的精灵
- 网络:守护进程;守护程序;虚拟光驱
可以在创建线程时候,直接设置daemon
eat_thread = threading.Thread(target=eat,args=("giao",),daemon=True)
也可以创建进程之后,启动线程之前,设置daemon
drink_thread = threading.Thread(target=drink,kwargs={"name":"qz","count":4})
drink_thread.daemon = True
看代码示例:
import threading
import time
def eat(name):
for i in range(4):
print(name+"我吃……")
time.sleep(0.5)
def drink(name,count):
for i in range(count):
print(name+"我喝……")
time.sleep(0.5)
if __name__ == '__main__':
eat_thread = threading.Thread(target=eat,args=("giao",),daemon=True)
drink_thread = threading.Thread(target=drink,kwargs={"name":"qz","count":4})
drink_thread.daemon = True
eat_thread.start()
drink_thread.start()
time.sleep(1)
print("我吃不下也喝不下了!")
运行结果如图:
可以清楚的看到,主线程结束之后,子线程也随即结束,不再运行。
五、线程间的执行顺序
线程之间的执行是无序的,是由CPU调度决定的。
我们可以用current_thread()方法获取线程对象,通过线程的名字来确定运行的顺序
代码示例:
import threading
import time
def test():
time.sleep(1)
thread = threading.current_thread()
print(thread)
if __name__ == '__main__':
for i in range(5):
test_thread = threading.Thread(target=test)
test_thread.start()
运行结果如图:
可以清楚的看到线程的执行顺序是无序的。
六、进程和线程对比
1、关系对比
线程是依附在进程里面的,没有进程就没有线程
一个进程默认提供一条线程,进程可以创建多个线程
2、区别对比
创建进程的资源开销要比创建线程的资源开销要大
进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
线程不能独立执行,必须依存在进程中
3、优缺点对比
进程优点:可以用多核;缺点:资源开销大
线程优点:资源开销小;缺点:不能使用多核(因为线程依附于进程,进程占用一个核)