Python 如何处理大量线程?

2 投票
2 回答
2441 浏览
提问于 2025-04-17 14:35
# data is a list  

Threading_list=[]

class myfunction(threading.Thread):

    def __init__(self,val):
        .......
    .......

     def run(self):
        .......
        ....... 

for i in range(100000):

    t=myfunction(data[i]) # need to execute this function on every datapoint 
    t.start()
    Threading_list.append(t)

for t in Threading_list:
    t.join()

这段代码会创建大约100000个线程,但我最多只能创建32个线程。请问这个代码可以怎么改?

2 个回答

0

这里有一个例子,它可以计算一个任意长度列表中每个数字的平方,使用了32个线程,通过一个叫做 ThreadPoolExecutor 的工具。正如Ellioh所说,在某些情况下你可能不想使用线程,这时候你可以很方便地切换到 ProcessPoolExecutor

import concurrent.futures

def my_function(x):
    return 2**x

data = [1, 6, 9, 3, 8, 4, 213, 534]

with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
    result = list(executor.map(my_function, data))

print(result)
4

在Python中,创建很多线程其实很少需要。更重要的是,我几乎想不出有什么理由需要这么做。其实有一些合适的设计模式可以解决并行执行代码的问题,这些模式会限制线程的数量。其中一个就是反应器模式

你到底想做什么呢?

另外要记住,由于全局解释器锁(GIL)的存在,Python的线程在处理计算任务时并不会提升性能,即使是在多处理器和多内核的系统上(顺便说一句,真的会有100000个内核的系统吗?我对此表示怀疑。:))。唯一能提升性能的机会是,如果计算部分是在用C/C++编写的模块中执行,这些模块在工作时不需要获取GIL。通常,Python线程是用来并行执行包含阻塞I/O操作的代码。

更新:注意到有stackless-python标签。根据我所知,它支持微线程。不过,你到底想做什么还是不太清楚。

如果你只是想处理100000个值(对每个值应用一个公式?),那么最好写成这样:

def myfunction(val):
    ....
    return something_calculated_from_val

results = [myfunction(d) for d in data] # you may use "map(myfunction, data)" instead

这样应该会好很多,除非myfunction()执行了一些阻塞的I/O操作。如果有的话,ThreadPoolExecutor可能真的会有帮助。

撰写回答