多執行緒 vs 多程序
- 程式:一堆程式碼以文字形式存入一個文件
- 程序:程式執行的一個狀態(鄰居對門的關係)
- 包含地址,空間,記憶體,資料棧等
- 每個程序有自己獨立的執行環境,多程序共享資料是一個問題
- 執行緒:(在一個屋拼居的關係)
- 一個程序的獨立執行片段,一個程序可以由多個執行緒組成
- 一個程序的多個執行緒間共享資料和上下文執行環境
- 互斥
- 全域性直譯器鎖(GIL)
- python程式碼的執行是由python虛擬機器進行控制
- 在主迴圈中只能有一個控制執行緒在執行
- 哪個變數需要執行緒共享資源多鎖哪個鎖並不是鎖住誰而是一個令牌
--------------------------------------------Lock鎖------------------------------------------------------------------
import threading sum = 0 loopsum = 100000 lock = threading.Lock() def MyAdd(): global sum , loopsum for i in range(1,loopsum): lock.acquire() sum += 1 lock.release() def MyMinu(): global sum , loopsum for i in range(1,loopsum): lock.acquire() sum -= 1 lock.release() if __name__=='__main__': print("{0}".format(sum)) t1 = threading.Thread(target=MyAdd) t2 = threading.Thread(target=MyMinu) t1.start() t2.start() t1.join() t2.join() print("{0}".format(sum))
------------------------------經過多長時間呼叫執行緒函式--threading.Timer-----------------------------------------------------
#經過多長時間呼叫執行緒函式 threading.Timer import threading import time def func(): print('開始') time.sleep(4) print('結束') if __name__=='__main__': t = threading.Timer(6,func) t.start() i = 0 while True: print('{}---------------'.format(i)) time.sleep(3) i+=1
-------------------------可重入鎖 一個鎖 可以被一個執行緒多次申請 主要解決遞迴申請的情況------------------------------------
#可重入鎖 一個鎖 可以被一個執行緒多次申請 主要解決遞迴申請鎖的情況 import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = self.name +'set num to '+str(num) print(msg) mutex.acquire() mutex.release() mutex.release() num = 0 mutex = threading.RLock() def test1(): for i in range(5): t = MyThread() t.start() if __name__=='__main__': test1()
- thread:有問題 不好用 python3 改成了_thread
----------------------------------------------- threading:通行的包------------------------------------------------------------
import time import threading def lo1(): print('函式1開始{}'.format(time.ctime())) time.sleep(4) print('函式1結束{}'.format(time.ctime())) def lo2(): print('函式2開始{}'.format(time.ctime())) time.sleep(2) print('函式2結束{}'.format(time.ctime())) def min(): print('呼叫倆個函式開始時間{}'.format(time.ctime())) t = threading.Thread(target=lo1,)#有引數傳args t.start() l = threading.Thread(target=lo2,) l.start() t.join() l.join() print('倆個函式結束時間{}'.format(time.ctime())) if __name__=='__main__': min()
- 守護執行緒
- 如果在程式中將子執行緒設定為守護執行緒則子執行緒會在主執行緒結束時自動退出
- 守護執行緒不重要或者不予許離開主執行緒
- 守護執行緒能否有效果跟環境有關
----------------------------------------------------- 非守護執行緒----------------------------------------------------------------
import time import threading def fun(): print('函式1開始{}'.format(time.ctime())) time.sleep(2) print('函式1結束{}'.format(time.ctime())) print('主執行緒開始') t = threading.Thread(target=fun) t.start() time.sleep(1) print('主執行緒結束')
-----------------------------------------------------守護執行緒-------------------------------------------------------------------
import time import threading def fun(): print('函式1開始{}'.format(time.ctime())) time.sleep(2) print('函式1結束{}'.format(time.ctime())) print('主執行緒開始') t = threading.Thread(target=fun) t.daemon=True t.start() time.sleep(1) print('主執行緒結束')
- 執行緒常用屬性
- threding.currentThread() #返回當前執行緒變數
- threading.enumerate() #返回一個包含正在執行的執行緒數量,效果跟 len(threading.enumerate)
- thr.setName #給執行緒設定名字
- thr.getName #得到執行緒的名字
---------------------------------直接例項一個子類 (需要重新寫run方法)--------------------------------------------------------
import threading import time class MyThread(threading.Thread): def __init__(self,arg): #注意可以不寫一旦寫必須呼叫父類的建構函式 super(MyThread,self).__init__() self.arg = arg def run(self): #注意一定要重寫run方法 所有任務都是run函式執行 time.sleep(2) print("Go!!!{}".format(self.arg)) for i in range(5): t = MyThread(i) t.start() t.join() print('走完程式')
-----------------------------------------------企業裡比較實用的寫法------------------------------------------------------------
import threading import time loop = [4,2] class ThreadFunc: def __init__(self,name): self.name = name def loop(self,nloop,nsec): """ :param nloop: loop 函式的名稱 :param nsec: 系統休眠的時間 :return: """ print('啟動迴路 ',nloop,'at',time.ctime()) time.sleep(nsec) print('完後迴圈 ',nloop,'at',time.ctime()) def main(): print('開始時間:',time.ctime()) t = ThreadFunc("loop") t1 = threading.Thread(target=t.loop,args=("LOOP1!",4)) t2 = threading.Thread(target=ThreadFunc('loop').loop,args=("LOOP2!",2)) t1.start() t2.start() t1.join() t2.join() print("程式走完",time.ctime()) if __name__=='__main__': main()
-----------------------------------------------互斥鎖-----------------------------------------------------------------------
import threading sum = 0 loopsum = 100000 lock = threading.Lock() def MyAdd(): global sum , loopsum for i in range(1,loopsum): lock.acquire() #上鎖 sum += 1 lock.release() #解鎖 def MyMinu(): global sum , loopsum for i in range(1,loopsum): lock.acquire() #上鎖 sum -= 1 lock.release() #解鎖 if __name__=='__main__': print("{0}".format(sum)) t1 = threading.Thread(target=MyAdd) t2 = threading.Thread(target=MyMinu) t1.start() t2.start() t1.join() t2.join() print("{0}".format(sum))
---------------------------------------------------建立執行緒池--------------------------------------------------------------------
import time import threading import queue class Producer(threading.Thread): def fun(self): global queue count = 0 while True: if queue.qsize() < 1000: for i in range(100): count += 1 msg = "生成產品"+str(count) queue.put(msg) print(msg) time.sleep(0.5) class Counmer(threading.Thread): def run(self): global queue while True: if queue.qsize()>100: for i in range(3): msg = self.name +'消費了'+queue.get() print(msg) time.sleep(1) if __name__=="__main__": queue = queue.Queue() for i in range(500): queue.put("初始產品"+str(i)) for i in range(2): p = Producer() p.start() for i in range(5): c = Counmer() c.start()
-----------------------------------------------多長時間後呼叫執行緒--------------------------------------------------------------
#經過多長時間呼叫執行緒函式 threading.Timer import threading import time def func(): print('開始') time.sleep(4) print('結束') if __name__=='__main__': t = threading.Timer(6,func) t.start() i = 0 while True: print('{}---------------'.format(i)) time.sleep(3) i+=1
-----------------------------------------------重入鎖----------------------------------------------------------------------------
#可重入鎖 一個鎖 可以被一個執行緒多次申請 主要解決遞迴申請鎖的情況 import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = self.name +'set num to '+str(num) print(msg) mutex.acquire() mutex.release() mutex.release() num = 0 mutex = threading.RLock() def test1(): for i in range(5): t = MyThread() t.start() if __name__=='__main__': test1()