多線程模塊 threading
-
創(chuàng)建多線程的兩種方式:
import threading import time
-
創(chuàng)建線程的第一種方式
def foo(n): pass print('hello world') t1 = threading.Thread(target=foo, args=(1,)) t1.start()
-
創(chuàng)建線程的第二種方式
```
class MyThread(threading.Thread):
def __init__(self, num):
threading.Thread.__init__(self)
self.num = num # 對(duì)象里的字段 # self 是 t1或t2
def run(self):
print("running on number: %s" % self.num)
time.sleep(3)
if __name__ == '__main__':
t1 = MyThread(1) # 實(shí)例化一個(gè)類的對(duì)象并村,執(zhí)行構(gòu)造方法
t2 = MyThread(2)
t1.start()
t2.start()
```
- 創(chuàng)建線程:
import threading
t1 = threading.Thread(target=music, args=('七里香',))
target指向函數(shù)挤茄,args指向函數(shù)的參數(shù)
-
啟動(dòng)線程:
t.start()
-
阻塞線程:
t.join() 阻塞直到線程t結(jié)束
-
多線程實(shí)例1
import threading from time import ctime, sleep import time # 預(yù)計(jì)耗時(shí)4秒 def music(func): for i in range(2): print("I was listening to %s. %s" % (func, ctime())) sleep(2) print("end listening %s" %ctime()) # 預(yù)計(jì)耗時(shí)6秒 def movie(func): for i in range(2): print("Begin watching at the %s! %s" % (func,ctime())) sleep(3) print("end watching %s" % ctime()) # 創(chuàng)建線程1析校,2 threads = [] t1 = threading.Thread(target=music, args=('七里香',)) threads.append(t1) t2 = threading.Thread(target=movie, args=('十三區(qū)',)) threads.append(t2) if __name__ == '__main__': for t in threads: t.start() start = time.time() t2.join() end = time.time() # t2.join() # join阻塞 print("總共耗時(shí) %s" % (end-start)) # 結(jié)果:總共耗時(shí) 6.004828929901123
-
多線程 -- 計(jì)算密集型
import threading import time begin = time.time() def add(n): sum = 0 for i in range(n): sum += i print(sum) # 單線程串行計(jì)算 # add(10000000) # add(10000000) # 多線程并行計(jì)算 t1 = threading.Thread(target=add, args=(10000000,)) t1.start() # print('1開始了') t2 = threading.Thread(target=add, args=(10000000,)) t2.start() # print('2也開始了') t1.join() t2.join() # end = time.time() print(end-begin) # 串行花費(fèi) 14.73 秒 兩者都是計(jì)算密集型,都在搶CPU # 并行花費(fèi) 15.71 秒 并行反而更多侮腹,因?yàn)榍袚Q還需要時(shí)間 # IO密集型任務(wù)或函數(shù) # 計(jì)算密集型任務(wù) # GIL全局解釋鎖 如果只有一顆CPU,無(wú)法解決計(jì)算密集型的任務(wù) 只有Cpython有這個(gè)bug
-
多線程 -- IO密集型
import time import threading def foo(n): # 設(shè)定3秒 print('線程1開始') print('foo %s' % n) # print('foo') time.sleep(3) print('線程1結(jié)束\n') def bar(n): # 設(shè)定1秒 print('線程2開始') print('bar %s' % n) time.sleep(1) # print('ok') print('線程2結(jié)束') # t1 t2 即為線程 # target = 要執(zhí)行的函數(shù) args = 參數(shù) t1 = threading.Thread(target=foo, args=(1,)) t2 = threading.Thread(target=bar, args=(2,)) print('...... in the main ........') # 線程執(zhí)行 start() begin = time.time() t1.start() # 線程開始 t2.start() # 線程開始 t1.join() # 子線程不結(jié)束不往下走 t2.join() # 子線程不結(jié)束不往下走 end = time.time() print('整個(gè)程序一共花了', end - begin, '秒,asshole') # # 運(yùn)行結(jié)果: 整個(gè)程序一共花了 3.003476858139038 秒几睛,asshole
-
死鎖
# 死鎖怎么辦? # 用遞歸鎖解決死鎖問題粤攒,遞歸鎖可重用 import threading, time class myThread(threading.Thread): def doA(self): # lockA.acquire() lock.acquire() # 加鎖 # 為什么在外面加了一把鎖后還要在里面再加一把鎖 print(self.name, "gotlockA", time.ctime()) time.sleep(1) # lockB.acquire() lock.acquire() # 加第二把鎖 print(self.name, "gotlockB", time.ctime()) # lockB.release() lock.release() # 釋放第一把鎖 # lockA.release() lock.release() # 釋放第二把鎖 def doB(self): lock.acquire() print(self.name, "gotlockB", time.ctime()) time.sleep(1) lock.acquire() print(self.name, "gotlockA", time.ctime()) lock.release() lock.release() def run(self): # 類似于構(gòu)造方法 self.doA() self.doB() if __name__ == "__main__": # lockA = threading.Lock() # 普通鎖 # lockB = threading.Lock() lock = threading.RLock() # Rlock 叫遞歸鎖所森,可重用 threads = [] for i in range(5): threads.append(myThread()) for t in threads: t.start() for t in threads: t.join() # 等待線程結(jié)束,后面再講夯接。
-
同步鎖
# 加鎖后會(huì)加鎖的部分變成串行 import time import threading def addNum(): global num # 在每個(gè)線程中都獲取這個(gè)變量 print('fuck off') # num -= 1 # 此操作的時(shí)間遠(yuǎn)小于CPU切換的時(shí)間 # 加鎖焕济,被加鎖的部分是串行 r.acquire() ####### 加鎖 temp = num # 1 # time.sleep(0.001) # 2 有可能取了數(shù)99后,執(zhí)行完這兩步后CPU轉(zhuǎn)到另外的線程上去了, print('ok') # 另外的線程取到99盔几,執(zhí)行減1晴弃,CPU再轉(zhuǎn)回當(dāng)前線程,又執(zhí)行99-1逊拍,重復(fù)了 time.sleep(0.0002) num = temp - 1 r.release() ######## 釋放鎖 num = 100 thread_list = [] r = threading.Lock() # python的GIL鎖 # 用for循環(huán)創(chuàng)建100個(gè)線程 for i in range(100): t = threading.Thread(target=addNum) t.start() # t.join() # join阻塞上鞠,可以得到正確的結(jié)果,從但是變成了串行芯丧,失去了多線程的意義 # join雖然可以得到正確結(jié)果芍阎,但是除了計(jì)算的其他部分也會(huì)變成并行 thread_list.append(t) for t in thread_list: t.join() print("\nfinal num:", num) # num減1的速度如果 # GIL保證只有一個(gè)線程進(jìn)入解釋器 # 自己加的鎖是鎖CPU,在我釋放鎖之前你不要切換了
-
event
# event 類似condition # event.isSet():返回event的狀態(tài)值注整; # # event.wait():如果 event.isSet()==False將阻塞線程能曾; # # event.set(): 設(shè)置event的狀態(tài)值為True,所有阻塞池的線程激活進(jìn)入就緒狀態(tài)肿轨, 等待操作系統(tǒng)調(diào)度寿冕; # # event.clear():恢復(fù)event的狀態(tài)值為False。 import threading, time class Boss(threading.Thread): def run(self): print("BOSS: 今晚大家都要加班到22:00") event.is_set() or event.set() time.sleep(2) print("BOSS:<22:00>可以下班了椒袍。 ") event.is_set() or event.set() class Worker(threading.Thread): def run(self): event.wait() print("Worker:哎驼唱,命苦啊") time.sleep(0.25) event.clear() event.wait() print("Worker: OhYear!") if __name__ == "__main__": event = threading.Event() threads = [] for i in range(5): threads.append(Worker()) threads.append(Boss()) for t in threads: t.start() for t in threads: t.join()
-
多線程利器 QUEUE隊(duì)列
# 隊(duì)列里本身就有一把鎖 # # import queue, time, threading # # d = queue.Queue(3) # # d.put('jinxing',0) #插入數(shù)據(jù) # d.put('xiaohu') # d.put('haoran') # # print(d.get()) # print(d.get()) # print(d.get()) # # # print(d.qsize()) # li = [1,2,3,4,5] # # def pri(): # while li: # a = li[-1] # print(a) # time.sleep(1) # try: # li.remove(a) # except: # print('----',a) # # t1 = threading.Thread(target=pri, args=()) # t1.start() # t2 = threading.Thread(target=pri, args=()) # t2.start() import threading, queue from time import sleep from random import randint class Production(threading.Thread): # 生產(chǎn)者 def run(self): while True: r = randint(0, 100) q.put(r) print("生產(chǎn)出來(lái)%s號(hào)包子" % r) sleep(1) class Proces(threading.Thread): # 消費(fèi)者 def run(self): while True: re = q.get() print("吃掉%s號(hào)包子" % re) sleep(1) if __name__ == "__main__": q = queue.Queue(10) threads = [Production(), Production(), Production(), Proces()] for t in threads: t.start()