multiprocessing
多進程基本使用
- 示例代碼1
import time
import random
from multiprocessing import Process
def run(name):
print(f'{name} is running')
time.sleep(random.randint(1,3))
print(f'{name} is end')
if __name__ =='__main__':
p_list = []
for i in range(3):
# 傳參的兩種方式
# p = Process(target=run,kwargs={'name':f'線程{i}'})
p = Process(target=run,args=(f"線程{i}",))
p_list.append(p)
p.start()
# for i in p_list:
# p.join() # join后主進程會等待子進程都結束再結束
print('主進程結束')
# strat():方法的功能 1.開啟進程 2.執行功能
- 示例代碼2
import os
import time
import random
from multiprocessing import Process
class Run(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self): # 必須實現run方法
print(os.getppid(),os.getpid())
print(f'{self.name} is running')
time.sleep(random.randint(1,3))
print(f'{self.name} is end')
if __name__ =='__main__':
p_list = []
for i in range(5):
p = Run(f'線程{i}')
p_list.append(p)
p.start()
for i in p_list:
p.join()
print('主進程結束',os.getpid())
進程池(from multiprocessing import Pool)
- 進程池原理
- 示例代碼(串行)
import os
import time
from multiprocessing import Pool
def task(n):
print('{} is running'.format(os.getpid()))
time.sleep(2)
print('{} is done'.format(os.getpid()))
return n**2
if __name__ == '__main__':
# print(os.cpu_count()) #查看cpu個數
p = Pool(4) # 最大四個進程
for i in range(1,7): # 開7個任務
ret = p.apply(task,args=(i,)) #同步的,一個運行完才執行另一個
print(f'本次任務結束:{ret}')
p.close() # 禁止往進程池內在添加任務
p.join() # 等待進程池
print('主進程')
- 示例代碼(並行)
import os
import time
from multiprocessing import Pool
def task(n):
print('{} is running'.format(os.getpid()))
time.sleep(2)
print('{} is done'.format(os.getpid()))
return n**2
if __name__ == '__main__':
# print(os.cpu_count()) #查看cpu個數
ret_lis = []
p = Pool(4) # 最大四個進程
for i in range(1,7): # 開7個任務
ret = p.apply_async(task,args=(i,)) # 異步的,一個運行完才執行另一個
ret_lis.append(ret)
p.close() # 禁止往進程池內在添加任務
p.join() # 等待進程池
# print('主進程')
print(_.get() for _ in ret_lis)
更多參數請參考:https://www.cnblogs.com/damumu/p/7321732.html
線程池(from multiprocessing.dummy import Pool)
- 線程池的原理
- 線程池首先會維護一個任務隊列
- 生成工作使用的線程(可以是自定義個數,也可以是系統默認)
- 線程分別從隊列中取出任務,並執行,一個任務執行完成需要告訴主線程完成一個任務
- 再從任務隊列中取出任務,直到所有任務為空,退出線程
- 為什么需要使用線程池
- 創建/銷毀線程伴隨着系統開銷,過於頻繁的創建/銷毀線程,會很大程度上影響處理效率。
記創建線程消耗時間T1,執行任務消耗時間T2,銷毀線程消耗時間T3,如果T1+T3>T2,那說明開啟一個線程來執行這個任務太不划算了!在線程池緩存線程可用已有的閑置線程來執行新任務,避免了創建/銷毀帶來的系統開銷。
- 線程並發數量過多,搶占系統資源從而導致阻塞。
線程能共享系統資源,如果同時執行的線程過多,就有可能導致系統資源不足而產生阻塞的情況。
- 對線程進行一些簡單的管理。
比如:延時執行、定時循環執行的策略等,運用線程池都能進行很好的實現。 - 示例代碼
import requests
from multiprocessing.dummy import Pool
def get_source(url):
ret = requests.get(url)
return ret.text
def main():
urls = [
# ...,
# ...,
# ...,
]
pool = Pool(5)
ret_list = pool.map(get_source, urls)
pool.close()
# 調用join之前,先調用close函數,否則會出錯。執行完close后不會有新的線程加入到pool,
# join函數等待所有子線程結束
pool.join()
for ret in ret_list:
print(ret)
print('*'*100)
# 更多關於dummy的介紹:https://my.oschina.net/zyzzy/blog/115096
if __name__ == '__main__':
main()