您好,登錄后才能下訂單哦!
這篇文章主要介紹“python中Event事件、進程池、線程池以及協(xié)程的實例介紹”,在日常操作中,相信很多人在python中Event事件、進程池、線程池以及協(xié)程的實例介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”python中Event事件、進程池、線程池以及協(xié)程的實例介紹”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
Event事件
用來控制線程的執(zhí)行
出現(xiàn)e.wait(),就會把這個線程設(shè)置為False,就不能執(zhí)行這個任務(wù);
只要有一個線程出現(xiàn)e.set(),就會告訴Event對象,把有e.wait的用戶全部改為True,剩余的任務(wù)就會立馬去執(zhí)行。由一些線程去控制另一些線程,中間通過Event。
from threading import Event from threading import Thread import time # 調(diào)用Event實例化出對象 e = Event() # # # 若該方法出現(xiàn)在任務(wù)中,則為False,阻塞 # e.wait() # False # # 若該方法出現(xiàn)在任務(wù)中,則將其他線程的False改為True,進入就緒態(tài)和運行態(tài) # e.set() # True def light(): print('紅燈亮...') time.sleep(5) # 應(yīng)該發(fā)出信號,告訴其他線程準備執(zhí)行 e.set() # 將car中的False變?yōu)門rue print('綠燈亮...') def car(name): print('正在等紅燈...') # 讓所有汽車任務(wù)進入阻塞態(tài) e.wait() # False print(f'{name}正在加速飄逸...') # 讓一個light線程控制多個car線程 t = Thread(target=light) t.start() for i in range(10): t = Thread(target=car, args=(f'汽車{i}號', )) t.start()
進程池與線程池
進程池與線程池是用來控制當前程序允許創(chuàng)建(進程/線程)的數(shù)量
作用:保證在硬件允許的范圍內(nèi)創(chuàng)建(進程/線程)的數(shù)量
線程池使用一:
from concurrent.futures import ThreadPoolExecutor import time pool = ThreadPoolExecutor(5) # 5代表只能開啟5個進程, 不加默認使用cpu的進程數(shù) # ThreadPoolExecutor(5) # 5代表只能開啟5個線程 # pool.submit() #異步提交任務(wù), 括號里傳函數(shù)地址 def task(): print('線程任務(wù)開始了...') time.sleep(1) print('線程任務(wù)結(jié)束了...') for line in range(5): pool.submit(task)
使用二:
from concurrent.futures import ThreadPoolExecutor import time pool = ThreadPoolExecutor(5) # 5代表只能開啟5個進程, 不加默認使用cpu的進程數(shù) # ThreadPoolExecutor(5) # 5代表只能開啟5個線程 # pool.submit() #異步提交任務(wù), 括號里傳函數(shù)地址 def task(): print('線程任務(wù)開始了...') time.sleep(1) print('線程任務(wù)結(jié)束了...') return 123 # 回調(diào)函數(shù) def call_back(res): print(type(res)) res2 = res.result() # 注意:賦值操作不要與接收的res同名 print(res2) for line in range(5): pool.submit(task).add_done_callback(call_back)
pool.shutdown() 會讓所有線程池的任務(wù)結(jié)束后,才往下執(zhí)行代碼
多線程爬取梨視頻
利用requests模塊,封裝底層socket套接字
主頁中獲取所有視頻id號,拼接視頻詳情頁url
在視頻詳情頁中獲取真實視頻url srcUrl=
往真實視頻url地址發(fā)送請求獲取 視頻 二進制數(shù)據(jù)
最后把視頻二進制數(shù)據(jù)保存到本地
協(xié)程
進程: 資源單位
線程: 執(zhí)行單位
協(xié)程: 在單線程下實現(xiàn)并發(fā)
注意: 協(xié)程不是操作系統(tǒng)資源,目的是讓單線程實現(xiàn)并發(fā)
協(xié)程目的
操作系統(tǒng):使用多道技術(shù),切換 + 保存狀態(tài),一個是遇到IO, 另一個是CPU執(zhí)行時間過長
協(xié)程:通過手動模擬操作系統(tǒng) “多道計數(shù)”, 實現(xiàn) 切換 + 保存狀態(tài)
手動實現(xiàn),遇到IO切換,欺騙操作系統(tǒng)誤以為沒有IO操作
單線程時,遇到IO,就切換 + 保存狀態(tài)
單線程時,對于計算密集型,來回切換 + 保存狀態(tài)反而效率更低
優(yōu)點:在IO密集型的情況下,會提高效率
缺點:若在計算密集型的情況下,來回切換,反而效率更低
import time def func1(): for i in range(10000000): i+1 def func2(): for i in range(10000000): i+1 start = time.time() func1() func2() stop = time.time() print(stop - start) # 1.0312113761901855 # 基于yield實現(xiàn)并發(fā) 在計算密集型的情況下效率更低 def func1(): while True: 10000000+1 yield def func2(): g = func1() for i in range(10000000): i+1 next(g) # 每次執(zhí)行next相當于切換到func1下面 start = time.time() func2() stop = time.time() print(stop - start) # 1.3294126987457275
gevent
gevent是一個第三方模塊,可以幫你監(jiān)聽IO操作,并切換
使用gevent的目的:在單線程下實現(xiàn),遇到IO就會 保存狀態(tài) + 切換
import time from gevent import monkey monkey.patch_all() # 可以監(jiān)聽該程序下所有的IO操作 from gevent import spawn, joinall # 用于做切換 + 保存狀態(tài) def func1(): print('1') time.sleep(1) # IO操作 def func2(): print('2') time.sleep(3) def func3(): print('3') time.sleep(5) start = time.time() s1 = spawn(func1) s2 = spawn(func2) s3 = spawn(func3) s1.join() # 發(fā)送信號,相當于等待自己(在單線程的情況下) s2.join() s3.join() # joinall((s1, s2, s3)) # 一個個執(zhí)行很麻煩,可以用joinall把這些全部裝進去 end = time.time() print(end - start) # 5.006161451339722
TCP服務(wù)端socket套接字實現(xiàn)協(xié)程
服務(wù)端:
from gevent import monkey from gevent import spawn import socket monkey.patch_all() server = socket.socket() server.bind(('127.0.0.1', 9999)) server.listen(5) def task(conn): while True: try: data = conn.recv(1024) if len(data) == 0: break print(data.decode('utf-8')) send_data = data.upper() conn.send(send_data) except Exception: break conn.close() def server2(): while True: conn, addr = server.accept() print(addr) spawn(task, conn) if __name__ == '__main__': s = spawn(server2) s.join()
客戶端:
import socket from threading import Thread, current_thread def client(): client = socket.socket() client.connect(('127.0.0.1', 9999)) number = 0 while True: send_data = f'{current_thread().name} {number}' client.send(send_data.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8')) number += 1 for i in range(400): t = Thread(target=client) t.start()
到此,關(guān)于“python中Event事件、進程池、線程池以及協(xié)程的實例介紹”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。