当前位置: 首页 > 后端技术 > Python

Python线程

时间:2023-03-26 11:08:58 Python

线程模块Python标准库提供了两个线程模块:_thread和threading。_thread提供低级的原始线程和一个简单的互斥锁,与线程模块相比,它相对有限。threading模块是_thread模块的替代品。在实际开发中,大多数情况下还是会使用高级模块threading。创建线程对象的语法如下:importthreadingthreading.Thread(target=None,name=None,args=())主要参数说明:target为函数名,即要调用的函数。name设置线程名称。args是函数需要的参数,以元组的形式传入。主要方法说明:run():用于表示线程活动的方法。start():启动线程活动。join():等待线程终止。isAlive():返回线程是否存活。getName():返回线程名称。setName():设置线程名称。函数式线程创建创建线程时,只需要传入一个执行函数和函数的参数即可。下面的例子使用thread类生成2个子线程,然后启动2个子线程,等待它们结束,#!/usr/bin/python#-*-coding:UTF-8-*-importthreadingimporttime,random,mathdefprint_num(idx):fornuminrange(idx):print("{0}\tnum={1}".format(threading.current_thread().getName(),num))delay=math.ceil(random.random()*2)time.sleep(delay)if__name__=='__main__':th1=threading.Thread(target=print_num,args=(2,),name="test1")th2=线程.Thread(target=print_num,args=(3,),name="test2")th1.start()th2.start()th1.join()th2.join()print("{0}over".format(threading.current_thread().getName()))运行结果如下:$pythonthread1.pytest1num=0test2num=0test1num=1test2num=1test2num=2MainThreadover运行脚本默认会启动一个线程,这就是所谓的主线程,主线程又开始了一个新的线程。Python的threading模块有一个current_thread()函数,会返回当前线程的实例,可以得到运行线程的名字。代码如下:threading.current_thread().getName()启动一个线程就是传入一个函数和参数,创建Thread实例,然后调用start()开始执行:th1=threading.Thread(target=print_num,args=(2,),name="test1")th1.start()从返回结果可以看出,主线程的名字是MainThread,子线程的名字是指定的时候创建。如果不给线程命名,Python会自动将线程命名为Thread-1、Thread-2等。创建线程类的方法是继承Thread类,重写Thread类的run()方法,在run()方法中定义具体要执行的任务。在Thread类中,提供了一个start()方法来启动一个新的线程,run()方法会在线程启动后自动调用。#!/usr/bin/python#-*-编码:UTF-8-*-导入线程导入时间、随机、数学类MutliThread(threading.Thread):def__init__(self,threadName,num):threading.Thread.__init__(self)self.name=threadNameself.num=numdefrun(self):foriinrange(self.num):print("{0}i={1}".format(threading.current_thread().getName(),i))delay=math.ceil(random.random()*2)time.sleep(delay)if__name__=='__main__':thr1=MutliThread("test1",3)thr2=MutliThread("test2",2)thr1.start()thr2.start()thr1.join()thr2.join()print("{0}over".format(threading.current_thread().getName()))运行结果为如下:$pythonthread2.pytest1i=0test2i=0test1i=1test2i=1test1i=2MainThreadover从返回结果可以看出,通过创建Thread类生成了两个线程对象thr1和thr2,重写run()函数,将业务逻辑放入其中,调用线程对象的start()方法启动线程。通过调用线程对象的join()函数等待线程完成。在守护线程的线程模块中,通过join()函数来使用子线程对象,主线程需要依赖子线程的执行才能继续执行。如果不使用join()函数,主线程和子线程并行运行,没有依赖关系。在多线程开发中,如果将子线程设置为守护线程,则守护线程会在主线程运行完毕后销毁。一个主线程可以设置多个守护线程。守护线程运行的前提是主线程必须存在。如果主线程不存在,守护线程就会被销毁。下面的例子创建了1个主线程和3个子线程,让主线程和子线程并行执行。代码如下:#!/usr/bin/python#-*-coding:UTF-8-*-importthreading,timedefrun(taskName):print("task:",taskName)time.sleep(2)print("{0}over".format(taskName))if__name__=='__main__':start_time=time.time()foriinrange(3):thr=threading.Thread(target=run,args=("task-{0}".format(i),))thr.start()print("{0}结束,thread_num={1}".format(threading.current_thread().getName(),threading.active_count()))print("costtime:",time.time()-start_time)结果如下:$pythonthread3.py('task:','task-0')('task:','task-1')('task:','task-2')MainThreadover,thread_num=4('costtime:',0.0011091232299804688)task-0overtask-1overtask-2over从返回的结果来看,可以可以看到当前线程数为4,主线程执行完后,直到子线程执行完,程序才会退出。在上面例子的基础上,使用线程对象的setDaemon(True)函数将所有子线程设置为守护线程。子线程成为守护线程后,只要主线程执行完毕,不管子线程是否执行完毕,程序都会退出。#!/usr/bin/python#-*-编码:UTF-8-*-导入线程,timedefrun(taskName):print("task:",taskName)time.sleep(2)print("{0}over".format(taskName))if__name__=='__main__':start_time=time.time()foriinrange(3):thr=threading.Thread(target=run,args=("task-{0}".format(i),))thr.setDaemon(True)thr.start()thrName=threading.current_thread().getName()thrCount=threading.active_count()print("{0}结束,thread_num={1}".format(thrName,thrCount))print("costtime:",time.time()-start_time)结果如下:$pythonthread4.py('task:','task-0')('task:','task-1')('task:','task-2')MainThreadover,thread_num=4('costtime:',0.0005180835723876953)从返回结果可以看出,经过主线程执行完毕,程序不等守护线程执行完就退出。要将线程对象设置为守护线程,必须在线程对象调用start()函数之前设置。