线程
线程
线程的概念
线程是被系统独立调度和分配的基本单位,也是程序执行流的最小单元,可以理解为是程序执行的一条分支
线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源
主线程
当一个程序启动,或有一个进程被操作系统(OS)创建,一个线程也立刻运行。该线程通常叫做程序的主线程,即程序启动就会创建一个主线程
主线程的重要性:
1.创建子线程
2.主线程需要最后完成执行,如执行各种关闭动作
子线程
子线程是程序执行的一条分支,子线程启动后会和主线程同时执行
threading模块
python的threading模块是比较底层的模块,该模块对thread进行了一些包装,使其可以被更加方便的使用
线程
1.使用多线程并发操作后,花费的时间要短很多
2.调用 start() 时,才会真正创建线程并开始执行
3.每个线程都有唯一标识符,来区分线程中的主次关系
4.主线程:main.Thread.mainfunc或程序主入口,称为主线程,子线程:threading.Thread()创建出来的是子线程
5.线程数量 = 主线程数 + 子线程数
6.主线程会等待所有子线程结束后才结束
7.python会自动为线程指定一个默认的名字
8.当线程的run()结束时该线程完成
9.线程的调度是由CPU根据当时的状态自行决定的,所以多个线程的执行是无序、随机的
10.无法控制线程调度程序,但可以通过其他方式来影响线程的调度方式
线程的参数传递
子线程的参数在创建线程对象时定义,传递参数有三种方式:
1.使用tuple传递
2.使用dict传递
3.混合使用tuple和dict传递
线程守护
子线程和主线程的一种约定,当主线程结束时,子线程也结束
如果没有设置线程守护,即使主程序exit(),子线程也会继续执行,因为主线程默认等待子线程结束才会退出,exit()并没有真正退出
threading
threading.Thread(target=func,[args=()/kwargs={}])
功能:创建子线程对象
参数:
target:子线程执行的函数名
args=()/kwargs={}:线程的参数列表,args=()为按顺序传递,kwargs={}为按关键字传递
threading.enumerate()
功能:获取当前所有活跃的线程对象列表
返回值:以线程对象为元素的list
threading.current_thread()
功能:获取当前线程对象
返回值:当前线程对象
obj.start()
功能:启动子线程
obj.setDaemon(bool)
功能:开启线程守护,需要在obj.start()前设置
参数:设置为True时开启线程守护,默认为False,即主线程结束时,子线程依然在执行
obj.join()
功能:让obj线程优先执行
threading.Lock
功能:创建互斥锁对象
Lock_obj.acquire()
功能:激活互斥锁
Lock_obj.release()
功能:释放互斥锁
import threading
import time
# 使用子线程同时执行多个函数
# 从执行结果可以看出,多线程程序的执行顺序是不确定的
# 执行到sleep()时,线程被阻塞(Blocked),sleep结束后线程进入就绪(Runnable)状态,等待调度,而线程调度将自行选择一个线程执行
def g1(a,b,c):
print('线程的参数:',a,b,c)
for i in range(2):
print('wow',threading.current_thread())
time.sleep(0.5)
def g2():
for i in range(2):
print('dota2',threading.current_thread())
time.sleep(0.5)
if __name__ == '__main__':
# 创建线程对象并传递参数
# t_wow = threading.Thread(target=g1,args=(1,2,3))
# t_wow = threading.Thread(target=g1,kwargs={'b':2,'c':3,'a':1})
t_wow = threading.Thread(target=g1,args=(1,),kwargs={'b':2,'c':3})
t_dota2 = threading.Thread(target=g2)
# 获取当前活跃的线程列表
thread_list1 = threading.enumerate()
print('当前活跃的线程数:',len(thread_list1))
print('当前活跃的线程:',thread_list1)
# 启动线程
t_wow.start()
t_dota2.start()
thread_list2 = threading.enumerate()
print('当前活跃的线程数:',len(thread_list2))
print('当前活跃的线程:',thread_list2)
# 定时获取活跃的线程数
while True:
thread_num = len(threading.enumerate())
print('当前活跃的线程数:',thread_num)
if thread_num <=1:
break
time.sleep(0.3)
# 线程守护
def work1():
for i in range(5):
print('正在work',i)
time.sleep(0.5)
if __name__ == '__main__':
thread_work = threading.Thread(target=work1)
thread_work.setDaemon(True)
thread_work.start()
time.sleep(2)
print('over')
exit()