15天學會爬蟲 第五天

爬蟲

第五天

多線程

線程的創建和運行

import multiprocessing

def task(num):
    pass
p1 = multiprocessing.Process(target = task)
p1.start()

守護線程

一般情況下,主線程代碼執行完畢後不會結束,會等待所有子線程任務結束後才結束
如果將子線程設置爲守護線程,意味着:主線程代碼執行完畢,主線程和子線程一起立即結束

t.setDaemom(True)

多線程的隊列

from queue import Queue

q = Queue()
q.put() # 數據放入隊列,隊列計數+1
q.get() # 從隊列中取出數據,隊列計數不變
q.task_done() # 和q.gert()配合使用,隊列計數-1
q.join() # 阻塞住線程

多進程

進程的創建和運行

import multiprocessing

def task(num):
    pass
p1 = multiprocessing
p1.start()

守護進程

將子進程設置爲守護進程後,主進程代碼執行完畢,主進程和子進程一起結束

p1.deamon=True

多進程的隊列

from multiprocessing import JoinableQueue as Queue

線程池

使用線程池多好處

  • 降低資源消耗.通過重複利用已經創建的線程降低線程創建和銷燬造成多消耗
  • 提高響應速度.當任務到達時,任務可以直接執行,而不需要等待新線程的創建
  • 提高線程的可管理性.線程時稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性
  • 使用線程池可以進行統一的分配,調優和監控

線程池的用法

from multiprocessing.dummy import Pool

def task():
    pass
pool = Pool(5) # 線程池中子線程的最大數量,當前爲5
pool.apply_async(func=task,args=(,)) # 發佈任務,交給線程池的子線程去執行,只是發佈
pool.close() # 關閉線程池,不在接收信多任務,不是銷燬線程池
pool.join() # 阻塞主線程,等待子線程中所有的任務結束

線程池的回調:
當不清楚線程池需要做的任務數量時,可以使用線程池的回調

def _callback(temp):
    print("---之前的線程任務執行完畢---")
pool.apply_async(func=task,callback=_callback) # 發佈任務,交給線程池的子線程去執行,只是發佈,當子線程執行完畢時,會自動調用callback

協程池

import gevent.monkey

gevent.monkey.patch_all()
# 協程池
from gevent.pool import Pool
from queue import Queue

# 協程池pool沒有close的方法

GIL鎖

全局解釋器鎖(GIL)是cpython解釋器中的,限制了多線程,導致統一時刻只有一個線程被調用,而且不能充分發揮CPU多核的特性

GIL的步驟

  • 切換到一個線程
  • 設置GIL鎖
  • 執行指定字節數量的代碼
    • 代碼執行完畢
    • 遇到延遲操作 「time.sleep(), socket.accept(), socket.connect()」等
  • 釋放GIL鎖
  • 切換到其他線程繼續執行

併發和並行

  • 有多核心,每個核心執行一個任務,任務數量 <= 核心數,此時並行
  • 任務數量 >= 核心數此時併發
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章