首頁 > 軟體

關於python執行緒池的四種實現方式

2023-11-26 14:00:44

python 執行緒池的四種實現方式

執行緒簡述

 一個程式執行起來後,一定有一個執行程式碼的東西,這個東西就是執行緒;
 一般計算(CPU)密集型任務適合多程序,IO密集型任務適合多執行緒;
一個程序可擁有多個並行的(concurrent)執行緒,當中每一個執行緒,共用當前程序的資源

以下是對發現的幾種多執行緒進行的彙總整理,均已測試執行 多執行緒實現的四種方式分別是:

multiprocessing下面有兩種:

from multiprocessing.dummy import Pool as ThreadPool  # 執行緒池

from multiprocessing.pool import ThreadPool   # 執行緒池,用法無區別,唯一區別這個是執行緒池

另外兩種:
from concurrent.futures import ThreadPoolExecutor  # python原生執行緒池,這個更主流

import threadpool  # 執行緒池,需要 pip install threadpool,很早之前的

方式1 multiprocessing.dummy Pool()

  • 非阻塞方法

multiprocessing.dummy.Pool.apply_async() 和 multiprocessing.dummy.Pool.imap()
執行緒並行執行

  • 阻塞方法

multiprocessing.dummy.Pool.apply()和 multiprocessing.dummy.Pool.map()
執行緒順序執行

from multiprocessing.dummy import Pool as Pool
import time

def func(msg):
    print('msg:', msg)
    time.sleep(2)
    print('end:')
    
pool = Pool(processes=3)
for i in range(1, 5):
    msg = 'hello %d' % (i)
    pool.apply_async(func, (msg,))  # 非阻塞,子執行緒有返回值
    # pool.apply(func,(msg,))       # 阻塞,apply()源自內建函數,用於間接的呼叫函數,並且按位元置把元祖或字典作為引數傳入。子執行緒無返回值
    # pool.imap(func,[msg,])        # 非阻塞, 注意與apply傳的引數的區別 無返回值
    # pool.map(func, [msg, ])       # 阻塞 子執行緒無返回值

print('Mark~~~~~~~~~~~~~~~')
pool.close()
pool.join()  # 呼叫join之前,先呼叫close函數,否則會出錯。執行完close後不會有新的程序加入到pool,join函數等待所有子程序結束
print('sub-process done')

執行結果:

方式2:multiprocessing.pool ThreadPool Threading()

from multiprocessing.pool import ThreadPool   # 執行緒池,用法無區別,唯一區別這個是執行緒池
from multiprocessing.dummy import Pool as ThreadPool  # 執行緒池
import os
import time

print("hi outside of main()")


def hello(x):
    print("inside hello()")
    print("Proccess id: %s" %(os.getpid()))
    time.sleep(3)
    return x*x


if __name__ == "__main__":
    p = ThreadPool(5)
    pool_output = p.map(hello, range(3))
    print(pool_output)

執行結果:

方式3:主流ThreadPoolExecutor

from concurrent.futures import ThreadPoolExecutor
import threading
import time

# 定義一個準備作為執行緒任務的函數
def action(max):
    my_sum = 0
    for i in range(max):
        print(threading.current_thread().name + '  ' + str(i))
        my_sum += i
    return my_sum
# 建立一個包含2條執行緒的執行緒池
pool = ThreadPoolExecutor(max_workers=2)
# 向執行緒池提交一個task, 20會作為action()函數的引數
future1 = pool.submit(action, 20)
# 向執行緒池再提交一個task, 30會作為action()函數的引數
future2 = pool.submit(action, 30)
# 判斷future1代表的任務是否結束
print(future1.done())
time.sleep(3)
# 判斷future2代表的任務是否結束
print(future2.done())
# 檢視future1代表的任務返回的結果
print(future1.result())
# 檢視future2代表的任務返回的結果
print(future2.result())
# 關閉執行緒池
pool.shutdown()

執行結果:

方式4:threadpool

需要 pip install threadpool

import threadpool


def hello(m, n, o):
    """"""
    print("m = %s, n = %s, o = %s" % (m, n, o))


if __name__ == '__main__':
    # 方法1
    # lst_vars_1 = ['1', '2', '3']
    # lst_vars_2 = ['4', '5', '6']
    # func_var = [(lst_vars_1, None), (lst_vars_2, None)]
    # 方法2
    dict_vars_1 = {'m': '1', 'n': '2', 'o': '3'}
    dict_vars_2 = {'m': '4', 'n': '5', 'o': '6'}
    func_var = [(None, dict_vars_1), (None, dict_vars_2)]
    # 定義了一個執行緒池,表示最多可以建立poolsize這麼多執行緒
    pool = threadpool.ThreadPool(2)
    # 呼叫makeRequests建立了要開啟多執行緒的函數,以及函數相關引數和回撥函數,其中回撥函數可以不寫
    requests = threadpool.makeRequests(hello, func_var)
    [pool.putRequest(req) for req in requests]   # 將所有要執行多執行緒的請求扔進執行緒池
    pool.wait()   # 等待所有執行緒完成工作後退出

"""
[pool.putRequest(req) for req in requests]等同於
  for req in requests:  
     pool.putRequest(req) 
"""

執行結果:

到此這篇關於關於python執行緒池的四種實現方式的文章就介紹到這了,更多相關python執行緒池實現內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com