線程模塊threading
阿新 • • 發佈:2018-10-04
eth 過程 數字 run info port 用戶 全局 proc
線程 -Threading模塊 -使用和進程基本相似
- 多線程中是可以
input
的 - 在使用的過程中從用戶層面上並沒有感覺到和進程的差別,但是有本質差別
- 執行代碼的最小單元
- 每一個進程至少有一個線程,這個線程是主線程
一個進程內的所有線程之間的數據是共享的
#啟動多線程 from threading import Thread import time def func(i): time.sleep(1) print(i) for i in range(10): t = Thread(target=func, args=(i,)) t.start() print(‘這是主線程執行的‘) #結果 這是主線程執行的 0 2 1 3 4 5 9 8 6 7 #這裏的十個數字是幾乎同時被輸出,說明是個線程並發
面向對象的形式啟動線程
#用面向對象的方法開啟新的線程 from threading import Thread class MyThread(Thread): #繼承Thread類 def __init__(self, arg): #重寫__init__方法,用於給這個類傳參 super().__init__() #繼承父類的__init__方法 self.arg = arg #將自己的參數賦給對象 def run(self): ‘‘‘objece.start()直接調用這個方法‘‘‘ self.methond() def methond(self): ‘‘‘這個類中的其他方法‘‘‘ print(self.arg)
進程|主線程|子線程
- 進程是最小的內存分配單位
- 線程是操作系統調度的最小單位
- 線程被cpu執行了
- 進程中可以有多個線層,至少一個主線程
- 主線程
- 子線程
- 子線程的數據儲存在棧中
- 全局變量
global n
線程共享
線程鎖 -這是解釋語言的一個不可避免的問題
- 全局解釋器鎖 -鎖的是線程
- 同一時刻只能有一個線程訪問cpu
進程和線程的效率對比 -線程快
from multiprocessing import Process from threading import Thread import time def cal_num(i): i += 1 if __name__ == ‘__main__‘: p_list = [] start = time.time() for i in range(100): #創建100個進程執行計算 p = Process(target=cal_num, args=(i, )) p.start() p_list.append(p) for i in p_list: i.join() end = time.time() t1 = end - start start = time.time() t_list = [] for i in range(100): t = Thread(target=cal_num, args=(i,)) t.start() t_list.append(t) for i in t_list: i.join() end = time.time() t2 = end - start print(‘100個進程消耗時間{} \n 100個線程消耗時間{}‘.format(t1, t2)) #結果 100個進程消耗時間0.19627618789672852 100個線程消耗時間0.009418964385986328
線程中的其他方法 -threading.方法名()
threading.current_thread()
所有進程的情況.get_ident()
查看進程的id.active_count()
查看活躍進程的數量.enumerate()
所有的進程情況放進一個列表中
守護線程 -守護線程和進程的區別
- 將子線程設置成守護線程,守護線程將在主線程代碼執行結束且其他線程執行結束後結束
- 但是守護進程是在主進程結束之後結束,不等待其他子進程是否結束
線程鎖 -Lock()和RLock
科學家吃面模型 -死鎖模型
Lock()
的死鎖現象Lock()
互斥鎖,只有一把鑰匙RLock()
遞歸鎖,只要拿到一把,就等於拿到一串,必須等一串全部歸還下個線程才能繼續拿鑰匙死鎖情況
#死鎖情況 from threading import Thread,Lock from time import sleep #死鎖情況 from threading import Thread,Lock,RLock from time import sleep mt_lock = Lock() cz_lock = Lock() def miantao(): mt_lock.acquire() print(‘拿到面條了‘) sleep(1) cz_lock.acquire() print(‘拿到叉子了‘) print(‘吃面‘) mt_lock.release() cz_lock.release() def chazi(): cz_lock.acquire() print(‘拿到叉子了‘) sleep(1) mt_lock.acquire() print(‘拿到面條了‘) print(‘吃面‘) cz_lock.release() mt_lock.release() th1 = Thread(target=miantao, args=()) th2 = Thread(target=chazi, args=()) th1.start() th2.start()
解決死鎖問題
RLock()
from threading import Thread, Lock, RLock from time import sleep cz_lock = mt_lock = RLock() #這裏創建遞歸鎖 def miantao(): mt_lock.acquire() print(‘拿到面條了‘) sleep(1) cz_lock.acquire() print(‘拿到叉子了‘) print(‘吃面‘) mt_lock.release() cz_lock.release() def chazi(): cz_lock.acquire() print(‘拿到叉子了‘) sleep(1) mt_lock.acquire() print(‘拿到面條了‘) print(‘吃面‘) cz_lock.release() mt_lock.release() th1 = Thread(target=miantao, args=()) th2 = Thread(target=chazi, args=()) th1.start() th2.start()
信號量 -同進程
- 限制一段代碼有且只有n個線程同時調用
事件 -同進程
創建就為阻塞狀態
實例 -鏈接數據庫,以及數據庫的可連接的情況
from threading import Thread, Event e = Event() def test(): ‘‘‘檢測數據庫的連通性‘‘‘ info = input(‘>>‘) if info == ‘1‘: e.set() print(‘數據庫網絡連接打開‘) else: print(‘關閉數據庫網絡連接‘) def connect_q(): ‘‘‘連接數據庫‘‘‘ print(‘等待數據庫網絡連接‘) e.wait() print(‘數據庫連接成功!‘) t1 = Thread(target=test) t2 = Thread(target=connect_q) t1.start() t2.start()
條件 -Condition
.acquire()
#鑰匙.release()
#釋放鑰匙.notify(num)
#允許鑰匙串有幾把鑰匙.wait()
#等待.notify(num)
提供鑰匙數量#條件 from threading import Condition, Thread def print_thrad(con, i): con.acquire() #這裏也有鎖 con.wait() print(‘第{}線程運行了‘.format(i)) con.release() num = int(input(‘>>‘)) con = Condition() for i in range(10): t = Thread(target=print_thrad, args=(con, i)) t.start() con.acquire() #這裏也有鎖 con.notify(num) #前後必須有鑰匙和鎖 con.release()
定時器 -Timer()
- 定時開啟一個線程
用法和
Threa()
一致from threading import Timer def func(): print(‘兩秒時間到了‘) Timer(2, func).start() print(‘呵呵‘) #結果 呵呵 兩秒時間到了 #子線程兩秒後才開啟
線程隊列 -queue.Queue()
.put()
放元素.put_nowait()
#放元素,沒有元素報錯.get()
#取出元素.get_nowait()
#沒有元素報錯
其他隊列模塊中的類
先進後出 LifoQueue()
優先級隊列 PriorityQueue()
線程模塊threading