一. 什么是线程
线程也是一种多任务编程的方式,可以使用计算机多核资源。线程又被称为轻量级的进程,线程具有以下特征:
- 线程是计算机核心分配的最小单位
- 一个进程可以包含多个线程
- 线程也是一个运行过程,也要消耗计算机资源;多个线程共享其进程的资源和空间
- 线程也拥有自己特有的资源属性,比如指令集,TID等
- 线程无论创建、删除还是运行,资源消耗都小于进程
- 多个线程之间并行执行,互不干扰
二. 创建线程
python中使用threading模块创建线程,关于threading模块的常用类/方法的使用总结如下:
类/方法 | 说明 |
import threading t = threading.Thread(name, target, *agrs, **kwargs) | 功能:创建线程对象 参数:name线程名称;target线程函数;args元组给线程函数传参;kwargs字典给线程函数传参 |
t.start() | 启动线程 |
t.join([timeout]) | 回收线程 |
t.is_alive() | 查看线程状态 |
t.name | 线程名称,默认为Thread-1 |
t.setName() | 设置线程名称 |
threading.currentThread() | 获取当前线程对象 |
t.daemon t.setDaemon(True) | 设置守护线程 * 默认t.daemon=False,主线程退 出不会影响分支线程; * 如果设置为True,则主线程退出分支线程也会退出; * 主线程退出指的是所有非守护线程运行结束时,主线程才退出。(并不是主线程代码执行完,主线程就会立即退出) * daemon属性的设置在start前 * 一般设置daemon后,不会再使用join |
t.isDaemon() | 判断daemon属性 |
示例代码一 创建Thread的实例,传递一个函数
from threading import Thread,currentThread
from time import sleep
def fun_thread(sec,tname):
'''线程函数,用于修改线程的名称'''
print("启动线程-->",currentThread().getName(),":",currentThread().is_alive())
print("setName修改线程名称")
currentThread().setName(tname)
sleep(sec)
print("{}线程结束".format(currentThread().getName()))
threads = [] # 维护线程
for i in range(3):
t = Thread(target=fun_thread, name="thread-%d"%i,
args=(3,"My"+str(i)+"Thread"))
threads.append(t)
t.start()
for t in threads:
t.join()
运行结果:
三. 封装自己的线程类
通过继承Thread类,并运行Thread类中的__init__方法以获取父类属性,并重写run方法,在线程启动后,将自动执行run方法。
示例代码二 创建Thread的实例,传递一个可调用的类实例
import threading
from time import sleep,ctime
from threading import currentThread
loops = [4,2]
class ThreadFunc(object):
def __init__(self, func, args):
self.func = func
self.args = args
def __call__(self):
self.func(*self.args)
def loop(nloop, nsec):
print(ctime(), currentThread().getName(), 'start loop', nloop)
sleep(nsec)
print(ctime(), currentThread().getName(), 'end loop', nloop)
def main():
threads = []
nloops = range(len(loops))
for i in nloops:
# 由于自定义的类中重写了__call__方法,使得类的实例可以像函数一样被调用
# 调用时会自动执行__call__这个特殊方法
t = threading.Thread(target=ThreadFunc(loop, (i, loops[i])))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
if __name__ == "__main__":
main()
运行结果:由于自定义的ThreadFunc类中重写了__call__方法,使得类的实例可以像函数一样被调用,调用时会自动执行__call__这个特殊方法。因此可以将类实例赋值给Thread的target参数。
示例代码三 派生Thread的子类,并创建子类的实例
import threading
from time import sleep, ctime
loops = (4, 2)
class MyThread(threading.Thread):
def __init__(self, target, args):
super().__init__()
self.target = target
self.args = args
def run(self):
self.target(*self.args)
def loop(nloop, nsec):
print(ctime(), 'start loop', nloop)
sleep(nsec)
print(ctime(), 'end loop', nloop)
def main():
threads = []
nloops = range(len(loops))
for i in nloops:
t = MyThread(loop,(i, loops[i]))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
if __name__ == "__main__":
main()