python创建线程
1、方法一:通过实例化threading.Thread类来创建线程,程序实例化了三个Thread类的实例,并向任务函数传递不同的参数,使它们运行不同的时间后结束,start()方法开启线程,join()方法阻塞主线程,等待当前线程运行结束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import time import threading def task_thread(counter): print (f '线程名称:{threading.current_thread().name} 参数: {counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}' ) num = counter while num: time.sleep( 3 ) num - = 1 print (f '线程名称:{threading.current_thread().name} 参数:{counter} 结束时间:{time.strftime("%Y-%m-%d %H:%M%S")}' ) if __name__ = = "__main__" : print (f '主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) #初始化三个线程,传递不同的参数 t1 = threading.Thread(target = task_thread,args = ( 3 ,)) t2 = threading.Thread(target = task_thread,args = ( 2 ,)) t3 = threading.Thread(target = task_thread, args = ( 1 ,)) #start()方法开启三个线程 t1.start() t2.start() t3.start() #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束 t1.join() t2.join() t3.join() print (f '主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) |
2、方法二:继承Thread类,在子类中重写run()和init()类
通过继承Thread类创建线程,以下程序自定义线程类MyThreading,继承自threading.Thread,并重写了__init__()方法和run()方法。其中run()方法相当于方法一中的任务函数,运行结果与方法一中的结果一致。
import time import threading class MyThread(threading.Thread): def __init__(self,counter): super().__init__() self.counter=counter def run(self): print(f'线程名称:{threading.current_thread().name} 参数: {self.counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}') counter=self.counter while counter: time.sleep(3) counter-=1 print(f'线程名称:{threading.current_thread().name} 参数: {self.counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M%S")}') if __name__=="__main__": print(f'主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}') #初始化三个线程,传递不同的参数 t1=MyThread(3) t2=MyThread(2) t3=MyThread(1) #start()方法开启三个线程 t1.start() t2.start() t3.start() #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束 t1.join() t2.join() t3.join() print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
如果继承Thread类,想调用外部传入函数,请看下面示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import time import threading def task_threading(counter): print (f '线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) num = counter while num: time.sleep( 3 ) num - = 1 print (f '线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) class MyThread(threading.Thread): def __init__( self ,target,args): super ().__init__() self .target = target self .args = args def run( self ): self .target( * self .args) if __name__ = = "__main__" : print (f '主线程开始的时间是:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) #初始化三个线程,传递不同的参数 t1 = MyThread(target = task_threading,args = ( 3 ,)) t2 = MyThread(target = task_threading,args = ( 2 ,)) t3 = MyThread(target = task_threading,args = ( 1 ,)) #start()方法开启三个线程 t1.start() t2.start() t3.start() #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束 t1.join() t2.join() t3.join() print (f '主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}' ) |
通过self.target来接收外部传入的函数,通过self.args来接收外部函数的参数,这样就可以使用继承Thread的线程类调用外部传入的函数。
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,这时候就需要互斥锁来进行同步,例如,在三个线程对共同变量num进行100万次加减操作后,其num的结果不为0.为了保证数据的正确性,需要使用互斥锁对多个线程进行同步,限制当一个线程正在访问数据时,其他只能等待,直到前一线程释放锁。使用threading.Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire和release方法,对于每次只运行一个线程操作的数据,可以将其操作放到acquire方法和release方法之间。
import time import threading num=0 lock=threading.Lock() def task_threading(n): global num #获取锁,用于线程同步 lock.acquire() for i in range(1000000): num=num+n num=num-n #释放锁,开启下一个线程 lock.release() #初始化三个线程,传递不同的参数 t1=threading.Thread(target=task_threading,args=(6,)) t2=threading.Thread(target=task_threading,args=(17,)) t3=threading.Thread(target=task_threading,args=(11,)) #start()方法开启三个线程 t1.start() t2.start() t3.start() #等待运行结束,join()方法阻塞主线程,等待当前线程运行结束 t1.join() t2.join() t3.join() print(num)
多线程同步之Semaphore(信号量) 互斥锁是只允许一个线程访问共享数据,而信号量是同时允许一定数量的线程访问共享数据,比如银行柜台有五个窗口,允许同时有5个人办理业务,后面的只能等待,待柜台有人办理完业务后才可以进入相应的柜台办理,示例如下,使用信号量控制并发:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import time import threading #同时只有5个人办理业务 #threading.BoundedSemaphore(value) values是一个内部计数,values默认是1,如果小于0,则会抛出 ValueError 异常,可以用于控制线程数并发数 semaphore = threading.BoundedSemaphore( 5 ) #模拟银行办理业务 def yewubanli(name): semaphore.acquire() time.sleep( 3 ) print (f "{time.strftime('%Y-%m-%d %H:%M:%S')} {name}正在办理业务" ) semaphore.release() thread_list = [] for i in range ( 12 ): t = threading.Thread(target = yewubanli,args = (i,)) thread_list.append(t) for thread in thread_list: thread.start() for thread in thread_list: thread.join() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)