多线程学习总结
一 起线程
以函数的方式以一个线程
import threading import time def run(n): print("task ", n) time.sleep(2) print("task done", n) start_time = time.time() t_objs = [] # 存线程实例 for i in range(10): 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...") print("cost:", time.time() - start_time)
测试时间略大于2秒. 主线程和这个主线程所启动的子线程是并行的,主线程的执行和子线程无关,要想在程序中让主线程等待子线程 的执行,只能加join() 方法.
二 以类的方式起线程
import threading import time class MyThread(threading.Thread): def __init__(self, n, sleep_time): super(MyThread, self).__init__() self.n = n self.sleep_time = sleep_time def run(self): # 重写父类的run 函数,所以只能是这个函数名 print("runnint task ", self.n) time.sleep(self.sleep_time) print("task done,", self.n) t1 = MyThread("t1", 2) t2 = MyThread("t2", 4) t1.start() t2.start() t1.join() t2.join() # 写上这两句之后,先把t1和t2执行完之后再执行print("main thread...."),不然就是先执行print("main thread....")
二 守护线程
import threading import time def run(n): print("task ",n ) time.sleep(5) print("task done",n,threading.current_thread()) start_time = time.time() t_objs = [] #存线程实例 for i in range(5): 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() time.sleep(1) print("----------all threads has finished...",threading.current_thread(),threading.active_count()) print("cost:",time.time() - start_time)
如果没有设置守护线程,
可以看出,是先把print 语句执行完之后,程序再等待执行所有子线程执行完的,
加上守护线程之后的结果
程序没有等待子线程执行完之后就退出了.
把join() 加上之后(也就是把那两行代码的注释取消之后)的结果:
这里主要是比较他们执行的顺序.
三 线程锁
import threading import time def run(n): lock.acquire() # 加锁, global num num += 1 time.sleep(0.2) lock.release() # 解锁 lock = threading.Lock() # 生成一个线程锁实例 num = 0 t_objs = [] # 存线程实例 for i in range(5): 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:", num)
加锁之后,在锁中间部分程序就是串行了,Python3中解释器自动加锁了,所以可以不再加锁,
四 递归锁
import threading, time def run1(): print("grab the first part data") lock.acquire() global num num += 1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() res = run1() #这里执行run1,而run1中已有锁,所以需要递归锁,使用和平常锁一样,只是在声明时声明为递归锁就行 print('--------between run1 and run2-----') res2 = run2() lock.release() print(res, res2) num, num2 = 0, 0 lock = threading.RLock() #声明为递归锁 for i in range(1): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num, num2)
递归锁和线程锁用法是一样的,只是需要在声明时声明成递归锁就行
五 信号量
import threading, 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(22): t = threading.Thread(target=run, args=(i,)) t.start() while threading.active_count() != 1: pass # print threading.active_count() else: print('----all threads done---') # print(num) # 信息号和线程锁用法一样,只是在声明时声明一个信息号就行
信息号和线程锁用法一样,只是在声明时声明一个信号量就行
六 事件Event
import time import threading 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] sees 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()
事件程序只有三种状态,set(), wait(),clear(),可以在这三种状态下分别做事情,
七 线程队列
# 生产者 消费者模型 import threading,time import queue q = queue.Queue(maxsize=10) # 定义一个共用的线程queue def Producer(name): count = 1 while True: q.put("包子%s" % count) print("生产了包子",count) count +=1 time.sleep(0.5) def Consumer(name): #while q.qsize()>0: while True: print("[%s] 取到[%s] 并且吃了它..." %(name, q.get())) time.sleep(1) p = threading.Thread(target=Producer,args=("zhangsan",)) c = threading.Thread(target=Consumer,args=("lishi",)) c1 = threading.Thread(target=Consumer,args=("wangwu",)) p.start() c.start() c1.start()