"""
1.什么是進程
一個正在運行的應(yīng)用程序就是一個進程,系統(tǒng)會給每個進程分配一個獨立的內(nèi)存區(qū)域,用來保存程序運行過程中產(chǎn)生的數(shù)據(jù),
當(dāng)進程結(jié)束的時候,這個內(nèi)存區(qū)域會自動銷毀。
2.什么是線程
進程想要執(zhí)行任務(wù)就必須要有線程。每個進程都默認有一個線程,這個線程叫主線程,其他的線程叫子線程。
程序任務(wù)都是默認在主線程中執(zhí)行的。
一個線程中執(zhí)行多個任務(wù),任務(wù)是串行執(zhí)行的(一個一個按順序執(zhí)行)
一個進程中如果有多個線程,多線程執(zhí)行不同任務(wù)的時候是并行(同時執(zhí)行,實質(zhì)是假象,是cpu在不同線程間來回調(diào)度,由GIL決定)
3.python全局GIL鎖
Python代碼的執(zhí)行由Python解釋器進行控制。目前Python的解釋器有多種,如CPython、PyPy、Jython等,
其中CPython為最廣泛使用的Python解釋器。理論上CPU是多核時支持多個線程同時執(zhí)行,
但在Python設(shè)計之初考慮到在Python解釋器的主循環(huán)中執(zhí)行Python代碼,于是CPython中設(shè)計了全局解釋器鎖
GIL(Global Interpreter Lock)機制用于管理解釋器的訪問,Python線程的執(zhí)行必須先競爭到GIL權(quán)限才能執(zhí)行。
全局解釋器鎖GIL機制流程
a、設(shè)置 GIL;
b、切換到一個線程去運行;
c、運行指定數(shù)量的字節(jié)碼指令或者線程主動讓出控制(可以調(diào)用 time.sleep(0));
d、把線程設(shè)置為睡眠狀態(tài);
e、解鎖 GIL;
d、再次重復(fù)以上所有步驟。
4.池的概念:
創(chuàng)建進程或線程都需要消耗時間,銷毀進程/線程也需要消耗時間。即便開啟了成千上萬的進程/線程,
操作系統(tǒng)也不能讓他們同時執(zhí)行,這樣反而會影響程序的效率。因此我們不能無限制的根據(jù)任務(wù)開啟或者結(jié)束進程/線程。
所以就有了池的概念。
定義一個池子,在里面放上固定數(shù)量的進程/線程,有需求來了,就拿一個池中的進程/線程來處理任務(wù),等到處理完畢,
并不關(guān)閉,而是將進程/線程再放回進程池中繼續(xù)等待任務(wù)。如果有很多任務(wù)需要執(zhí)行,池中的進程/線程數(shù)量不夠,
任務(wù)就要等待之前的進程/線程執(zhí)行任務(wù)完畢歸來,拿到空閑進程/線程才能繼續(xù)執(zhí)行。
減少了進程/線程創(chuàng)建/銷毀帶來的消耗,同時又可以最大化的利用CPU。
進程池/線程池數(shù)量的確定
知道了池的概念,那進程/線程開啟的數(shù)量該怎么確定呢?多少個進程/線程才能最大化利用CPU,并且不會給操作系統(tǒng)帶來額外的消耗呢?
進程數(shù):CPU數(shù)量 < 進程數(shù) < CPU數(shù)量*2
線程數(shù): CPU數(shù)量 * 5
"""
import re
import datetime
import requests
from multiprocessing.dummy import Pool as Threadpool
def get_msg(i):
url = "https://maoyan.com/board/4?offset=%s" % (i*10)
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
ret_html = requests.get(url=url, headers=headers)
ret_text = ret_html.text
patterns = re.compile('<a href=.*?data-act="boarditem-click" data-val=".*?">(.*?)</a>')
result = patterns.findall(ret_text)
return result
def main1():
all_result = []
for i in range(10):
result = get_msg(i)
all_result += result
print(all_result)
print(len(all_result))
def main():
th = Threadpool(5)
result = th.map(get_msg, [i for i in range(10)])
print(result)
if __name__ == '__main__':
starttime = datetime.datetime.now()
main()
endtime = datetime.datetime.now()
print(endtime - starttime)
print('-------------------------')
starttime = datetime.datetime.now()
main1()
endtime = datetime.datetime.now()
print(endtime - starttime)