python创建线程
1、方法一:通过实例化threading.Thread类来创建线程,程序实例化了三个Thread类的实例,并向任务函数传递不同的参数,使它们运行不同的时间后结束,start()方法开启线程,join()方法阻塞主线程,等待当前线程运行结束。
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类,想调用外部传入函数,请看下面示例:
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个人办理业务,后面的只能等待,待柜台有人办理完业务后才可以进入相应的柜台办理,示例如下,使用信号量控制并发:
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()