2017-10-04 73 views
0

我有一个代码,它基本上运行了一个无限循环,并且在循环的每次迭代中运行一些指令。其中一些指令必须以“并行”方式运行,我通过使用多处理来执行。这里是我的代码结构的一个例子:Python:无限循环中的多线程

from multiprocessing import Pool 
from multiprocessing.dummy import Pool as ThreadPool 

def buy_fruit(fruit, number): 
    print('I bought '+str(number)+' times the following fruit:'+fruit) 
    return 'ok' 

def func1(parameter1, parameter2): 
    myParameters=(parameter1,parameter2) 
    pool= Threadpool(2) 
    data = pool.starmap(func2,zip(myParameters)) 
    return 'ok' 

def func2(parameter1): 
    print(parameter1) 
    return 'ok' 



while true: 
    myFruits=('apple','pear','orange') 
    myQuantities=(5,10,2) 
    pool= Threadpool(2) 
    data = pool.starmap(buy_fruit,zip(myFruits,myQuantities)) 
    func1('hello', 'hola') 

我同意这是一个有点乱,因为我有主回路内的多进程,而且内的功能。

所以一切正常,直到循环运行几分钟,我得到一个错误: “RuntimeError:无法启动新的线程”

我在网上看到,这是由于这样的事实,我有打开了太多的线程。

在每次循环迭代结束时关闭所有线程的最简单方法是什么,所以我可以在新循环迭代开始时重新启动“新鲜”?

预先感谢您的时间和帮助!

最佳, 朱莉娅

PS:本示例代码仅仅是一个例子,我真正的函数打开许多线程,每个回路和每一个功能需要几秒钟来执行。

+3

查看Pool的_join()_函数,这可能是您正在寻找的内容 – Minato

+0

您可能想要在循环外部创建线程池。您可能需要在CPU绑定线程的上下文中阅读_global解释器lock_。 – moooeeeep

回答

0

您正在无限循环内创建一个新的ThreadPool对象,这可能是您的问题的原因,因为您没有在循环结束时终止线程。你有没有尝试在无限循环之外创建对象?

pool = ThreadPool(2) 
while True: 
    myFruits = ('apple','pear','orange') 
    myQuantities = (5,10,2) 
    data = pool.starmap(buy_fruit, zip(myFruits,myQuantities)) 

或者,并回答你的问题,如果你的使用情况由于某些原因需要在每次循环迭代创建一个新的线程池对象,使用ContextManager(with符号),以确保所有线程都在离开关闭ContextManager。

while True: 
    myFruits = ('apple','pear','orange') 
    myQuantities = (5,10,2) 
    with ThreadPool(2) as pool: 
     data = pool.starmap(buy_fruit, zip(myFruits,myQuantities)) 

但是请注意,与上面的代码相比,它的显着性能差异。创建和终止线程很昂贵,这就是为什么上面的例子运行得更快,而且可能是你想要使用的。

关于涉及“嵌套的ThreadPools”的编辑:我建议维护一个ThreadPool实例,并根据需要传递对嵌套函数的引用。

def func1(pool, parameter1, parameter2): 
    ... 
... 

pool = ThreadPool(2) 
while True: 
    myFruits=('apple','pear','orange') 
    myQuantities=(5,10,2) 
    data = pool.starmap(buy_fruit, zip(myFruits,myQuantities)) 
    func1(pool, 'hello', 'hola') 
+0

你好,感谢您的帮助。好吧,我想在主循环之外创建池是个好主意。问题是我的代码有点复杂,并且在主循环中,我调用了函数,它也有一些多线程(我编辑了我最初的问题)。有没有办法只是终止线程?唯一重要的是尽可能地执行同步功能。我不介意在主循环结束时等待关闭所有正在运行的线程。谢谢! –

+0

嘿@JuliaScivi。我不太清楚“终止线程”的含义。我们在这里使用的'ThreadPool'类是为了保持我们告诉它的线程数量,并提供将工作推送到这些线程的手段(比如通过'.starmap')。如果您希望能够将工作从另一个函数推送到'ThreadPool',只需将它的引用传递给该函数。您的工作将被同步执行,因为您只使用同步操作('starmap')。我编辑了我的答案来说明我的意思 –