真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

python線程池類函數(shù),線程池的構(gòu)造函數(shù)

python 線程池的使用

最近在做一個爬蟲相關(guān)的項目,單線程的整站爬蟲,耗時真的不是一般的巨大,運行一次也是心累,,,所以,要想實現(xiàn)整站爬蟲,多線程是不可避免的,那么python多線程又應(yīng)該怎樣實現(xiàn)呢?這里主要要幾個問題(關(guān)于python多線程的GIL問題就不再說了,網(wǎng)上太多了)。

10年積累的成都網(wǎng)站設(shè)計、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計制作后付款的網(wǎng)站建設(shè)流程,更有崖州免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

一、 既然多線程可以縮短程序運行時間,那么,是不是線程數(shù)量越多越好呢?

顯然,并不是,每一個線程的從生成到消亡也是需要時間和資源的,太多的線程會占用過多的系統(tǒng)資源(內(nèi)存開銷,cpu開銷),而且生成太多的線程時間也是可觀的,很可能會得不償失,這里給出一個最佳線程數(shù)量的計算方式:

最佳線程數(shù)的獲?。?/p>

1、通過用戶慢慢遞增來進(jìn)行性能壓測,觀察QPS(即每秒的響應(yīng)請求數(shù),也即是最大吞吐能力。),響應(yīng)時間

2、根據(jù)公式計算:服務(wù)器端最佳線程數(shù)量=((線程等待時間+線程cpu時間)/線程cpu時間) * cpu數(shù)量

3、單用戶壓測,查看CPU的消耗,然后直接乘以百分比,再進(jìn)行壓測,一般這個值的附近應(yīng)該就是最佳線程數(shù)量。

二、為什么要使用線程池?

對于任務(wù)數(shù)量不斷增加的程序,每有一個任務(wù)就生成一個線程,最終會導(dǎo)致線程數(shù)量的失控,例如,整站爬蟲,假設(shè)初始只有一個鏈接a,那么,這個時候只啟動一個線程,運行之后,得到這個鏈接對應(yīng)頁面上的b,c,d,,,等等新的鏈接,作為新任務(wù),這個時候,就要為這些新的鏈接生成新的線程,線程數(shù)量暴漲。在之后的運行中,線程數(shù)量還會不停的增加,完全無法控制。所以,對于任務(wù)數(shù)量不端增加的程序,固定線程數(shù)量的線程池是必要的。

三、如何使用線程池

過去使用threadpool模塊,現(xiàn)在一般使用concurrent.futures模塊,這個模塊是python3中自帶的模塊,但是,python2.7以上版本也可以安裝使用,具體使用方式如下:

注意到:

concurrent.futures.ThreadPoolExecutor,在提交任務(wù)的時候,有兩種方式,一種是submit()函數(shù),另一種是map()函數(shù),兩者的主要區(qū)別在于:

Python多線程總結(jié)

在實際處理數(shù)據(jù)時,因系統(tǒng)內(nèi)存有限,我們不可能一次把所有數(shù)據(jù)都導(dǎo)出進(jìn)行操作,所以需要批量導(dǎo)出依次操作。為了加快運行,我們會采用多線程的方法進(jìn)行數(shù)據(jù)處理, 以下為我總結(jié)的多線程批量處理數(shù)據(jù)的模板:

主要分為三大部分:

共分4部分對多線程的內(nèi)容進(jìn)行總結(jié)。

先為大家介紹線程的相關(guān)概念:

在飛車程序中,如果沒有多線程,我們就不能一邊聽歌一邊玩飛車,聽歌與玩 游戲 不能并行;在使用多線程后,我們就可以在玩 游戲 的同時聽背景音樂。在這個例子中啟動飛車程序就是一個進(jìn)程,玩 游戲 和聽音樂是兩個線程。

Python 提供了 threading 模塊來實現(xiàn)多線程:

因為新建線程系統(tǒng)需要分配資源、終止線程系統(tǒng)需要回收資源,所以如果可以重用線程,則可以減去新建/終止的開銷以提升性能。同時,使用線程池的語法比自己新建線程執(zhí)行線程更加簡潔。

Python 為我們提供了 ThreadPoolExecutor 來實現(xiàn)線程池,此線程池默認(rèn)子線程守護(hù)。它的適應(yīng)場景為突發(fā)性大量請求或需要大量線程完成任務(wù),但實際任務(wù)處理時間較短。

其中 max_workers 為線程池中的線程個數(shù),常用的遍歷方法有 map 和 submit+as_completed 。根據(jù)業(yè)務(wù)場景的不同,若我們需要輸出結(jié)果按遍歷順序返回,我們就用 map 方法,若想誰先完成就返回誰,我們就用 submit+as_complete 方法。

我們把一個時間段內(nèi)只允許一個線程使用的資源稱為臨界資源,對臨界資源的訪問,必須互斥的進(jìn)行?;コ?,也稱間接制約關(guān)系。線程互斥指當(dāng)一個線程訪問某臨界資源時,另一個想要訪問該臨界資源的線程必須等待。當(dāng)前訪問臨界資源的線程訪問結(jié)束,釋放該資源之后,另一個線程才能去訪問臨界資源。鎖的功能就是實現(xiàn)線程互斥。

我把線程互斥比作廁所包間上大號的過程,因為包間里只有一個坑,所以只允許一個人進(jìn)行大號。當(dāng)?shù)谝粋€人要上廁所時,會將門上上鎖,這時如果第二個人也想大號,那就必須等第一個人上完,將鎖解開后才能進(jìn)行,在這期間第二個人就只能在門外等著。這個過程與代碼中使用鎖的原理如出一轍,這里的坑就是臨界資源。 Python 的 threading 模塊引入了鎖。 threading 模塊提供了 Lock 類,它有如下方法加鎖和釋放鎖:

我們會發(fā)現(xiàn)這個程序只會打印“第一道鎖”,而且程序既沒有終止,也沒有繼續(xù)運行。這是因為 Lock 鎖在同一線程內(nèi)第一次加鎖之后還沒有釋放時,就進(jìn)行了第二次 acquire 請求,導(dǎo)致無法執(zhí)行 release ,所以鎖永遠(yuǎn)無法釋放,這就是死鎖。如果我們使用 RLock 就能正常運行,不會發(fā)生死鎖的狀態(tài)。

在主線程中定義 Lock 鎖,然后上鎖,再創(chuàng)建一個子 線程t 運行 main 函數(shù)釋放鎖,結(jié)果正常輸出,說明主線程上的鎖,可由子線程解鎖。

如果把上面的鎖改為 RLock 則報錯。在實際中設(shè)計程序時,我們會將每個功能分別封裝成一個函數(shù),每個函數(shù)中都可能會有臨界區(qū)域,所以就需要用到 RLock 。

一句話總結(jié)就是 Lock 不能套娃, RLock 可以套娃; Lock 可以由其他線程中的鎖進(jìn)行操作, RLock 只能由本線程進(jìn)行操作。

小白都看懂了,Python 中的線程和進(jìn)程精講,建議收藏

目錄

眾所周知,CPU是計算機(jī)的核心,它承擔(dān)了所有的計算任務(wù)。而操作系統(tǒng)是計算機(jī)的管理者,是一個大管家,它負(fù)責(zé)任務(wù)的調(diào)度,資源的分配和管理,統(tǒng)領(lǐng)整個計算機(jī)硬件。應(yīng)用程序是具有某種功能的程序,程序運行與操作系統(tǒng)之上

在很早的時候計算機(jī)并沒有線程這個概念,但是隨著時代的發(fā)展,只用進(jìn)程來處理程序出現(xiàn)很多的不足。如當(dāng)一個進(jìn)程堵塞時,整個程序會停止在堵塞處,并且如果頻繁的切換進(jìn)程,會浪費系統(tǒng)資源。所以線程出現(xiàn)了

線程是能擁有資源和獨立運行的最小單位,也是程序執(zhí)行的最小單位。一個進(jìn)程可以擁有多個線程,而且屬于同一個進(jìn)程的多個線程間會共享該進(jìn)行的資源

① 200 多本 Python 電子書(和經(jīng)典的書籍)應(yīng)該有

② Python標(biāo)準(zhǔn)庫資料(最全中文版)

③ 項目源碼(四五十個有趣且可靠的練手項目及源碼)

④ Python基礎(chǔ)入門、爬蟲、網(wǎng)絡(luò)開發(fā)、大數(shù)據(jù)分析方面的視頻(適合小白學(xué)習(xí))

⑤ Python學(xué)習(xí)路線圖(告別不入流的學(xué)習(xí))

私信我01即可獲取大量Python學(xué)習(xí)資源

進(jìn)程時一個具有一定功能的程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行過程。進(jìn)程由程序,數(shù)據(jù)集合和進(jìn)程控制塊三部分組成。程序用于描述進(jìn)程要完成的功能,是控制進(jìn)程執(zhí)行的指令集;數(shù)據(jù)集合是程序在執(zhí)行時需要的數(shù)據(jù)和工作區(qū);程序控制塊(PCB)包含程序的描述信息和控制信息,是進(jìn)程存在的唯一標(biāo)志

在Python中,通過兩個標(biāo)準(zhǔn)庫 thread 和 Threading 提供對線程的支持, threading 對 thread 進(jìn)行了封裝。 threading 模塊中提供了 Thread , Lock , RLOCK , Condition 等組件

在Python中線程和進(jìn)程的使用就是通過 Thread 這個類。這個類在我們的 thread 和 threading 模塊中。我們一般通過 threading 導(dǎo)入

默認(rèn)情況下,只要在解釋器中,如果沒有報錯,則說明線程可用

守護(hù)模式:

現(xiàn)在我們程序代碼中,有多個線程, 并且在這個幾個線程中都會去 操作同一部分內(nèi)容,那么如何實現(xiàn)這些數(shù)據(jù)的共享呢?

這時,可以使用 threading庫里面的鎖對象 Lock 去保護(hù)

Lock 對象的acquire方法 是申請鎖

每個線程在操作共享數(shù)據(jù)對象之前,都應(yīng)該申請獲取操作權(quán),也就是調(diào)用該共享數(shù)據(jù)對象對應(yīng)的鎖對象的acquire方法,如果線程A 執(zhí)行了 acquire() 方法,別的線程B 已經(jīng)申請到了這個鎖, 并且還沒有釋放,那么 線程A的代碼就在此處 等待 線程B 釋放鎖,不去執(zhí)行后面的代碼。

直到線程B 執(zhí)行了鎖的 release 方法釋放了這個鎖, 線程A 才可以獲取這個鎖,就可以執(zhí)行下面的代碼了

如:

到在使用多線程時,如果數(shù)據(jù)出現(xiàn)和自己預(yù)期不符的問題,就可以考慮是否是共享的數(shù)據(jù)被調(diào)用覆蓋的問題

使用 threading 庫里面的鎖對象 Lock 去保護(hù)

Python中的多進(jìn)程是通過multiprocessing包來實現(xiàn)的,和多線程的threading.Thread差不多,它可以利用multiprocessing.Process對象來創(chuàng)建一個進(jìn)程對象。這個進(jìn)程對象的方法和線程對象的方法差不多也有start(), run(), join()等方法,其中有一個方法不同Thread線程對象中的守護(hù)線程方法是setDeamon,而Process進(jìn)程對象的守護(hù)進(jìn)程是通過設(shè)置daemon屬性來完成的

守護(hù)模式:

其使用方法和線程的那個 Lock 使用方法類似

Manager的作用是提供多進(jìn)程共享的全局變量,Manager()方法會返回一個對象,該對象控制著一個服務(wù)進(jìn)程,該進(jìn)程中保存的對象運行其他進(jìn)程使用代理進(jìn)行操作

語法:

線程池的基類是 concurrent.futures 模塊中的 Executor , Executor 提供了兩個子類,即 ThreadPoolExecutor 和 ProcessPoolExecutor ,其中 ThreadPoolExecutor 用于創(chuàng)建線程池,而 ProcessPoolExecutor 用于創(chuàng)建進(jìn)程池

如果使用線程池/進(jìn)程池來管理并發(fā)編程,那么只要將相應(yīng)的 task 函數(shù)提交給線程池/進(jìn)程池,剩下的事情就由線程池/進(jìn)程池來搞定

Exectuor 提供了如下常用方法:

程序?qū)?task 函數(shù)提交(submit)給線程池后,submit 方法會返回一個 Future 對象,F(xiàn)uture 類主要用于獲取線程任務(wù)函數(shù)的返回值。由于線程任務(wù)會在新線程中以異步方式執(zhí)行,因此,線程執(zhí)行的函數(shù)相當(dāng)于一個“將來完成”的任務(wù),所以 Python 使用 Future 來代表

Future 提供了如下方法:

使用線程池來執(zhí)行線程任務(wù)的步驟如下:

最佳線程數(shù)目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數(shù)目

也可以低于 CPU 核心數(shù)

使用線程池來執(zhí)行線程任務(wù)的步驟如下:

關(guān)于進(jìn)程的開啟代碼一定要放在 if __name__ == '__main__': 代碼之下,不能放到函數(shù)中或其他地方

開啟進(jìn)程的技巧

開啟進(jìn)程的數(shù)量最好低于最大 CPU 核心數(shù)

python如何實現(xiàn)線程池

#這個類是線程類,用來在主程序中調(diào)用生成一個線程。其實線程池就是線程的集合地,

#能夠解決有效統(tǒng)一的管理線程,基本就達(dá)到了線程池的目的;

#這一段代碼是我的爬蟲程序中的一部分,希望對你有用。

class?Spider(Thread):

def?__init__(self,?todo_list):

super().__init__()

self.setDaemon(True)

self.todo_list?=?todo_list

self.stat?=?IDLE

def?is_idle(self):

return?self.stat?==?IDLE

def?run(self):

while?True:

url?=?self.todo_list.get()

#?開始線程工作

#這個函數(shù)就是主函數(shù)了,????????????

def?main(max_threads):

########這里和上一個函數(shù)就是核心代碼了。

#?創(chuàng)建?N?個線程,并啟動

print('Spawn?spiders')

spiders?=?[Spider(todo_list)?for?i?in?range(max_threads)]

for?spd?in?spiders:

spd.start()

#python主運行代碼:????????????

if?__name__?==?'__main__':

main(max_threads)

只能給你這么多解釋了,如果想弄懂,還是要去看看基礎(chǔ)知識的。

另外可以查一下有沒有封裝好的三方庫。


文章標(biāo)題:python線程池類函數(shù),線程池的構(gòu)造函數(shù)
網(wǎng)站路徑:http://weahome.cn/article/hoiejg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部