亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

實(shí)例代碼講解Python 線程池

 更新時(shí)間:2020年08月24日 11:19:04   作者:python技術(shù)  
這篇文章主要介紹了Python 線程池的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)python,感興趣的朋友可以了解下

大家都知道當(dāng)任務(wù)過(guò)多,任務(wù)量過(guò)大時(shí)如果想提高效率的一個(gè)最簡(jiǎn)單的方法就是用多線程去處理,比如爬取上萬(wàn)個(gè)網(wǎng)頁(yè)中的特定數(shù)據(jù),以及將爬取數(shù)據(jù)和清洗數(shù)據(jù)的工作交給不同的線程去處理,也就是生產(chǎn)者消費(fèi)者模式,都是典型的多線程使用場(chǎng)景。

那是不是意味著線程數(shù)量越多,程序的執(zhí)行效率就越快呢。

顯然不是。線程也是一個(gè)對(duì)象,是需要占用資源的,線程數(shù)量過(guò)多的話肯定會(huì)消耗過(guò)多的資源,同時(shí)線程間的上下文切換也是一筆不小的開(kāi)銷,所以有時(shí)候開(kāi)辟過(guò)多的線程不但不會(huì)提高程序的執(zhí)行效率,反而會(huì)適得其反使程序變慢,得不償失。

所以,如何確定多線程的數(shù)量是多線程編程中一個(gè)非常重要的問(wèn)題。好在經(jīng)過(guò)多年的摸索業(yè)界基本已形成一套默認(rèn)的標(biāo)準(zhǔn)。

對(duì)于 CPU 密集型的計(jì)算場(chǎng)景,理論上將線程的數(shù)量設(shè)置為 CPU 核數(shù)就是最合適的,這樣可以將每個(gè) CPU 核心的性能壓榨到極致,不過(guò)在工程上,線程的數(shù)量一般會(huì)設(shè)置為 CPU 核數(shù) + 1,這樣在某個(gè)線程因?yàn)槲粗蜃枞麜r(shí)多余的那個(gè)線程完全可以頂上。

而對(duì)于 I/O 密集型的應(yīng)用,就需要考慮 CPU 計(jì)算的耗時(shí)和 I/O 的耗時(shí)比了。如果 I/O 耗時(shí)和 CPU 耗時(shí) 為 1:1,那么兩個(gè)線程是最合適的,因?yàn)楫?dāng) A 線程做 I/O 操作時(shí),B 線程執(zhí)行 CPU 計(jì)算任務(wù),當(dāng) B 線程做 I/O 操作時(shí),A 線程執(zhí)行 CPU 計(jì)算任務(wù),CPU 和 I/O 的利用率都得到了百分百,完美。所以可以認(rèn)為最佳線程數(shù) = CPU 核數(shù) * [1 +(I/O 耗時(shí) / CPU 耗時(shí)]。

線程池

平時(shí)我們自己寫(xiě)多線程程序時(shí)基本都是直接調(diào)用 Thread(target=method) 即可,實(shí)際上創(chuàng)建線程遠(yuǎn)沒(méi)有這么簡(jiǎn)單,需要分配內(nèi)存,同時(shí)線程還需要調(diào)用操作系統(tǒng)內(nèi)核的 API,然后操作系統(tǒng)還需要為線程分配一系列的資源,過(guò)程很是復(fù)雜,所以要盡量避免頻繁的創(chuàng)建和銷毀線程。

回想一下自己平時(shí)寫(xiě)多線程代碼的模式,是不是當(dāng)任務(wù)來(lái)臨時(shí)直接創(chuàng)建線程,執(zhí)行任務(wù),當(dāng)任務(wù)執(zhí)行結(jié)束之后,線程也就隨之消亡了。然后又開(kāi)始循環(huán)往復(fù)。有多少個(gè)任務(wù)就創(chuàng)建了多少個(gè)線程。這種模式的話很浪費(fèi)硬件資源。

那如何避免這種問(wèn)題呢,線程池就派上用場(chǎng)了。

其實(shí)線程池就是生產(chǎn)者消費(fèi)者模式的最佳實(shí)踐,當(dāng)線程池初始化時(shí),會(huì)自動(dòng)創(chuàng)建指定數(shù)量的線程,有任務(wù)到達(dá)時(shí)直接從線程池中取一個(gè)空閑線程來(lái)用即可,當(dāng)任務(wù)執(zhí)行結(jié)束時(shí)線程不會(huì)消亡而是直接進(jìn)入空閑狀態(tài),繼續(xù)等待下一個(gè)任務(wù)。而隨著任務(wù)的增加線程池中的可用線程必將逐漸減少,當(dāng)減少至零時(shí),任務(wù)就需要等待了。

在 python 中使用線程池有兩種方式,一種是基于第三方庫(kù) threadpool,另一種是基于 python3 新引入的庫(kù) concurrent.futures.ThreadPoolExecutor。這里我們都做一下介紹。

threadpool 方式

使用 threadpool 前需要先安裝一下,看了這么久我們的文章,相信你很快就會(huì)搞定的。在命令行執(zhí)行如下命令即可。

pip install threadpool

以下是一個(gè)簡(jiǎn)易的線程池使用模版,我們創(chuàng)建了一個(gè)函數(shù) sayhello,然后創(chuàng)建了一個(gè)大小為 2 的線程池,也就是線程池總共有兩個(gè)活躍線程。

最后通過(guò) pool.putRequest() 將任務(wù)丟到線程池執(zhí), pool.wait() 等待所有線程結(jié)束。同時(shí)我們還可以定義回調(diào)函數(shù),拿到任務(wù)的返回結(jié)果。

由結(jié)果我們可以看出,線程池中的確只有兩個(gè)線程,分別為 Thread-1Thread-2

import time
import threadpool
import threading

def sayhello(name):
  print("%s say Hello to %s" % (threading.current_thread().getName(), name));
  time.sleep(1)
  return name

def callback(request, result): # 回調(diào)函數(shù),用于取回結(jié)果
  print("callback result = %s" % result)

name_list =['admin','root','scott','tiger']
start_time = time.time()
pool = threadpool.ThreadPool(2) # 創(chuàng)建線程池
requests = threadpool.makeRequests(sayhello, name_list, callback) # 創(chuàng)建任務(wù)
[pool.putRequest(req) for req in requests] # 加入任務(wù)
pool.wait() 
print('%s cost %d second' % (threading.current_thread().getName(), time.time()-start_time))

## 運(yùn)行結(jié)果如下
Thread-1 say Hello to admin
Thread-2 say Hello to root
Thread-1 say Hello to scott
Thread-2 say Hello to tiger
callback result = admin
callback result = root
callback result = tiger
callback result = scott
MainThread cost 2 second

ThreadPoolExecutor 方式

ThreadPoolExecutor 是 python3 新引入的庫(kù),具體使用方法與 threadpool 大同小異,同樣是創(chuàng)建容量為 2 的線程池,提交四個(gè)任務(wù)。只不過(guò)這里分別是通過(guò) submit as_completed 來(lái)提交和獲取任務(wù)返回結(jié)果的。

同樣由輸出結(jié)果我們可以看出,兩種線程池的實(shí)現(xiàn)方式中關(guān)于線程的命名方式是不一致的。

import time
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed

def sayhello(name):
  print("%s say Hello to %s" % (threading.current_thread().getName(), name));
  time.sleep(1)
  return name

name_list =['admin','root','scott','tiger']
start_time = time.time()
with ThreadPoolExecutor(2) as executor: # 創(chuàng)建 ThreadPoolExecutor 
  future_list = [executor.submit(sayhello, name) for name in name_list] # 提交任務(wù)

for future in as_completed(future_list):
  result = future.result() # 獲取任務(wù)結(jié)果
  print("%s get result : %s" % (threading.current_thread().getName(), result))

print('%s cost %d second' % (threading.current_thread().getName(), time.time()-start_time))

## 運(yùn)行結(jié)果如下
ThreadPoolExecutor-0_0 say Hello to admin
ThreadPoolExecutor-0_1 say Hello to root
ThreadPoolExecutor-0_0 say Hello to scott
ThreadPoolExecutor-0_1 say Hello to tiger
MainThread get result : root
MainThread get result : tiger
MainThread get result : scott
MainThread get result : admin
MainThread cost 2 second

線程池總結(jié)

本文介紹了常用的兩種線程池的實(shí)現(xiàn)方式,在多線程編程中能使用線程池就不要自己去創(chuàng)建線程,并不是說(shuō)線程池實(shí)現(xiàn)的多么好,其實(shí)我們自己完全也可以實(shí)現(xiàn)一個(gè)功能更強(qiáng)大的線程池。但是其內(nèi)置的線程池一來(lái)是受過(guò)全方面測(cè)試的,在安全性,性能和方便性上基本就是最優(yōu)的了,同時(shí)線程池還替我們做了很多額外的工作,比如任務(wù)隊(duì)列的維護(hù),線程銷毀時(shí)資源的回收等都不需要開(kāi)發(fā)者去關(guān)心,我們只需注重業(yè)務(wù)邏輯即可,不需要在關(guān)心其他額外的工作,這將大大提高我們的的工作效率和使用感受。

當(dāng)然其自帶的線程池也不是十全十美的,至少暫時(shí)沒(méi)有提供動(dòng)態(tài)添加任務(wù)的入口出來(lái)。而且在設(shè)計(jì)方面不夠靈活,比如我想線程池只維護(hù)一個(gè)核心數(shù)量,也就是上文說(shuō)的最大數(shù)量。但是當(dāng)任務(wù)過(guò)多時(shí)可以再額外創(chuàng)建出一些新的線程(閾值可以自定義),處理完之后這些多余的線程將自動(dòng)銷毀,目前這個(gè)是做不到的。

代碼地址

https://github.com/JustDoPython/python-100-day/tree/master/day-053

參考資料

https://chrisarndt.de/projects/threadpool/api/

以上就是實(shí)例代碼講解Python 線程池的詳細(xì)內(nèi)容,更多關(guān)于Python 線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • scrapy+flask+html打造搜索引擎的示例代碼

    scrapy+flask+html打造搜索引擎的示例代碼

    本文主要介紹了scrapy+flask+html打造搜索引擎的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 使用python把Excel中的數(shù)據(jù)在頁(yè)面中可視化

    使用python把Excel中的數(shù)據(jù)在頁(yè)面中可視化

    最近學(xué)習(xí)數(shù)據(jù)分析,感覺(jué)Python做數(shù)據(jù)分析真的好用,下面這篇文章主要給大家介紹了關(guān)于如何使用python把Excel中的數(shù)據(jù)在頁(yè)面中可視化的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Python使用requests發(fā)送POST請(qǐng)求實(shí)例代碼

    Python使用requests發(fā)送POST請(qǐng)求實(shí)例代碼

    這篇文章主要介紹了Python使用requests發(fā)送POST請(qǐng)求實(shí)例代碼,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • python實(shí)現(xiàn)批量修改文件名代碼

    python實(shí)現(xiàn)批量修改文件名代碼

    本文給大家分享的是一段僅僅10行代碼就實(shí)現(xiàn)了批量修改文件名的python腳本,推薦給大家,有需要的小伙伴可以參考下
    2017-09-09
  • Python實(shí)用技巧之臨時(shí)文件的妙用

    Python實(shí)用技巧之臨時(shí)文件的妙用

    當(dāng)我們用Python編寫(xiě)程序時(shí),有時(shí)候需要臨時(shí)存儲(chǔ)數(shù)據(jù)且不希望占用多少內(nèi)存,這些情況下以創(chuàng)建臨時(shí)文件的方式進(jìn)行處理,既不會(huì)干擾本地文件系統(tǒng),又安全省事。本文主要介紹了臨時(shí)文件的一些妙用,希望大家能夠喜歡
    2023-02-02
  • python使用Matplotlib繪圖及設(shè)置實(shí)例(用python制圖)

    python使用Matplotlib繪圖及設(shè)置實(shí)例(用python制圖)

    Python matplotlib包可以畫(huà)各種類型的圖,功能非常齊全,下面這篇文章主要給大家介紹了關(guān)于python使用Matplotlib繪圖及設(shè)置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • python opencv 檢測(cè)移動(dòng)物體并截圖保存實(shí)例

    python opencv 檢測(cè)移動(dòng)物體并截圖保存實(shí)例

    這篇文章主要介紹了python opencv 檢測(cè)移動(dòng)物體并截圖保存實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03
  • Django 全局的static和templates的使用詳解

    Django 全局的static和templates的使用詳解

    這篇文章主要介紹了Django 全局的static和templates的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • python學(xué)習(xí)開(kāi)發(fā)mock接口

    python學(xué)習(xí)開(kāi)發(fā)mock接口

    這篇文章主要為大家詳細(xì)介紹了python學(xué)習(xí)開(kāi)發(fā)mock接口的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • python re正則表達(dá)式模塊(Regular Expression)

    python re正則表達(dá)式模塊(Regular Expression)

    Python 的 re 模塊(Regular Expression 正則表達(dá)式)提供各種正則表達(dá)式的匹配操作,在文本解析、復(fù)雜字符串分析和信息提取時(shí)是一個(gè)非常有用的工具.
    2014-07-07

最新評(píng)論