1、CPU密集型 CPython中使用到了GIL,多线程的时候锁相互竞争,且多核优势不能发挥,选用Python多进程效率更 高。即使用ProcessPoolExecutor 2、IO密集型 在Python中适合是用多线程,可以减少多进程间IO的序列化开销。且在IO等待的时候,切换到其他线程 继续执行,效率不错。即ThreadPoolExecutor
ThreadPoolExecutor 和 ProcessPoolExecutor 都是python中的并发执行框架,但它们之间有一些区别: 线程 vs 进程:ThreadPoolExecutor 使用线程池来执行任务,而 ProcessPoolExecutor 使用进程池来执行任务。因为线程是在同一个进程内运行的,所以线程之间共享了进程的内存空间,这意味着线程之间的通信和数据共享比进程更容易。但是,由于 Python 的全局解释器锁(GIL)的存在,同一时刻只有一个线程可以执行 Python 代码,这意味着在 CPU 密集型任务中,多线程并不能真正发挥多核 CPU 的优势。而进程之间是相互独立的,不受 GIL 的限制,可以充分利用多核 CPU 资源。
适用场景:由于 GIL 的限制,ThreadPoolExecutor 更适合于 I/O 密集型任务,如网络请求、文件读写等操作,而 ProcessPoolExecutor 更适合于 CPU 密集型任务,如大量计算、图像处理等操作。
系统资源消耗:由于进程之间是相互独立的,ProcessPoolExecutor 需要更多的系统资源来维护进程之间的通信和数据共享,而 ThreadPoolExecutor 只需要维护线程之间的通信和数据共享,所以在系统资源有限的情况下,ThreadPoolExecutor 更加适合。
ThreadPoolExecutor代码示例
pythonfrom concurrent.futures import ThreadPoolExecutor
import concurrent
def func():
pass
with ThreadPoolExecutor(max_workers=15) as executor:
tasks = {}
case_number = 0
finished = 0
for idx, row in df.iterrows():
tasks[executor.submit(func, session, row['col1'])] = (row['col2'], row['col3'])
case_number += 1
split_part_num = case_number // 200
for future in concurrent.futures.as_completed(tasks):
cate_id_list, cate_name_list, confidence_list = future.result()
request_id, row_list = tasks[future]
name, code = tasks[future]
if len(cate_name_list.split(';')) >= 1:
res_cate_name = cate_name_list.split(';')[0]
res_cate_id = cate_id_list.split(';')[0]
# res_confidence = confidence_list.split(';')[0]
res_confidence = confidence_list[0]
cate_path = back_tree[res_cate_id]
res_data.append([name, code, res_cate_id, res_cate_name, cate_path, res_confidence])
else:
res_data.append(['', '', '', ''])
finished += 1
if finished % split_part_num == 0:
print("【 total finished:{}% 】".format(0.5 * finished / split_part_num))
print('done')
本文作者:brucewu
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!