python成长之路【第十一篇】:网络编程之线程threading模块
一、threading模块介绍
threading 模块建立在 _thread 模块之上。thread 模块以低级、原始的方式来处理和控制线程,而 threading 模块通过对 thread 进行二次封装,提供了更方便的 api 来处理线程。
示例:
import threading import time def process(arg): time.sleep(1) print(arg) # 普通方式 # for i in range(10): # process(i) # 多线程方式,创建了10个线程 for i in range(10): t = threading.Thread(target=process, args=(i,)) t.start()
thread方法说明: t.start() : 激活线程 t.getName() : 获取线程的名称 t.setName() : 设置线程的名称 t.name : 获取或设置线程的名称 t.is_alive() : 判断线程是否为激活状态 t.isAlive() :判断线程是否为激活状态 t.setDaemon() 设置为后台线程或前台线程(默认:False);通过一个布尔值设置线程是否为守护线程,必须在执行start()方法之后才可以使用。如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止;如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 t.isDaemon() : 判断是否为守护线程 t.ident :获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才有效,否则它只返回None。 t.join() :逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义 t.run() :线程被cpu调度后自动执行线程对象的run方法
示例2:使用类的方式
import threading class MyThread(threading.Thread): def __init__(self, n): super(MyThread, self).__init__() self.n = n def run(self): print("running task ", self.n) t1 = MyThread("t1") t2 = MyThread("t2") t1.start() t2.start()
二、线程锁threading.RLock和threading.Lock
我们使用线程对数据进行操作的时候,如果多个线程同时修改某个数据,可能会出现不可预料的结果,为了保证数据的准确性,引入了锁的概念。
示例:
# 锁lock,为了实现各个线程协同修改num。 import threading import time num = 0 lock = threading.Lock() def run(n): lock.acquire() #获得锁 global num num += 1 # time.sleep(1) lock.release() #释放锁 t_objs = [] #存放线程实例 for i in range(50): t = threading.Thread(target=run, args=("t-%s" %i,)) t.start() t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 for t in t_objs: #循环线程实例列表,等待所有线程执行完毕 t.join() print("------all threads has finished...",threading.current_thread(),threading.active_count()) print("num %s" % num)
threading.RLock和threading.Lock 的区别
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。 如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
import threading lock = threading.Lock() #Lock对象 lock.acquire() lock.acquire() #产生了死琐。 lock.release() lock.release() import threading rLock = threading.RLock() #RLock对象 rLock.acquire() rLock.acquire() #在同一线程内,程序不会堵塞。 rLock.release() rLock.release()
三、threading.Event
Event是线程间通信最间的机制之一:一个线程发送一个event信号,其他的线程则等待这个信号。用于主线程控制其他线程的执行。 Events 管理一个flag,这个flag可以使用set()设置成True或者使用clear()重置为False,wait()则用于阻塞,在flag为True之前。flag默认为False。
Event.wait([timeout]) : 堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)。 Event.set() :将标识位设为Ture Event.clear() : 将标识位设为False。 Event.isSet() :判断标识位是否为Ture。
当线程执行的时候,如果flag为False,则线程会阻塞,当flag为True的时候,线程不会阻塞。它提供了本地和远程的并发性。
示例:# 实现红灯停,绿灯行
import threading import time event = threading.Event() def lighter(): count = 0 event.set() #先设置绿灯 while True: if count > 5 and count < 10: #改成红灯 event.clear() #把标志位清了 print("\033[41;1mred light is on...\033[0m") elif count > 10: event.set() #变绿灯 count = 0 else: print("\033[42;1mgreen light is on...\033[0m") time.sleep(1) count += 1 def car(name): while True: if event.is_set(): #代表绿灯 print("[%s] running..."% name) time.sleep(1) else: print("[%s] see red light,waiting..." % name) event.wait() print("\033[34;1m[%s] green light is on, start going...\033[0m" % name) light = threading.Thread(target=lighter,) light.start() car1 = threading.Thread(target=car,args=("Tesla",)) car1.start() car2 = threading.Thread(target=car,args=("BMW",)) car2.start()
四、semaphore信号量
示例:
import threading import time def run(n): semaphore.acquire() time.sleep(1) print("run the thread: %s\n" % n) semaphore.release() if __name__ == '__main__': semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 for i in range(20): t = threading.Thread(target=run, args=(i,)) t.start() while threading.active_count() != 1: pass # print threading.active_count() else: print('----all threads done---')
五、设置子线程
示例:
import threading import time def run(n): print("task ", n) time.sleep(2) print("task done",n,threading.current_thread()) start_time = time.time() t_objs = [] #存放线程实例 for i in range(50): t = threading.Thread(target=run, args=("t-%s" %i,)) t.setDaemon(True) #把当前线程设置为守护线程 t.start() t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 # for t in t_objs: # t.join() print("------all threads has finished...",threading.current_thread(),threading.active_count()) print("cost:",time.time() - start_time)