关于executer.thread()迭代限制及多线程使用限制的技术咨询
ThreadPoolExecutor.map迭代限制及2000次循环多线程场景的限制
一、executor.map()的迭代限制
- 参数长度必须匹配:
map要求所有传入的可迭代参数长度一致,它会按索引取各参数的元素调用目标函数。如果参数长度不一样,会以最短的那个为准,超出的元素直接被忽略。比如你代码里传的三个参数都是长度为2的列表,所以filterProductBasicInformation会被调用2次,这可能和你预期的处理逻辑不符。 - 异常会中断遍历:只要有一次任务调用抛出异常,遍历
map返回的迭代器时就会直接抛出这个异常,后面的结果就拿不到了(除非你捕获异常后继续遍历),不像submit能单独处理每个任务的异常。 - 结果顺序严格按任务提交顺序来:哪怕后面的任务先执行完,也要等前面的任务结果返回后才会输出对应的结果,要是前面的任务跑的慢,后面的结果就会被拖着。
- 大任务队列可能占内存:如果传入的可迭代对象特别大,
map会把所有任务都提交到线程池队列里,要是任务参数本身也很大,容易导致内存占用过高。
二、2000次循环场景下多线程的限制
- 线程池任务排队开销:你设置的
max_workers=4,意味着同时最多跑4个线程。2000次循环会提交大量任务,线程池会自动排队,但任务队列的管理多少会有一些开销,不过这个量级一般不会有大问题。 - GIL对CPU密集型任务的限制:如果
filterProductBasicInformation是CPU密集型的(比如大量计算),Python的GIL会让同一时刻只有一个线程执行Python代码,多线程不仅不会提速,反而会因为线程切换增加额外开销。但如果是IO密集型任务(比如读文件、发请求),GIL影响很小,多线程能有效提高效率。 - 大参数的内存占用:你每次循环都传
all_sku_basic_information这类大对象,虽然是引用传递,但任务排队期间这些对象会被持有,要是对象特别大,可能会占不少内存,不过任务完成后引用计数会自动释放,问题不大。 - 结果收集的内存压力:2000次循环每次都生成
results列表存结果,如果每个结果数据量不小,累计下来内存会吃紧,建议边处理结果边释放,别全存着。 - 你代码里的潜在问题:每次循环都重新初始化
results = [],之前循环的结果会被直接覆盖;而且你传的参数是长度为2的列表,每次循环都会调用两次filterProductBasicInformation,这大概率不符合你的业务逻辑,得检查参数传递是否正确。
内容的提问来源于stack exchange,提问作者Deep Kumar Singh
相关产品推荐
相关产品推荐

