我的问题如下:我有multiprocessing.pool.ThreadPool
个worker_count
个工作对象和一个主pqueue
,我可以从中将任务提供给池。
流程如下:有一个主循环从level
获取pqueue
级别的项目,并使用apply_async
将其提交到池中。处理该项目时,它会生成level + 1
项。问题是池接受所有任务并按照提交的顺序处理它们。
更确切地说,正在发生的事情是处理level 0
个项目,每个项目生成100个level 1
项目,这些项目立即从pqueue
检索并添加到池中,每个{{1} item生成提交到池中的100个level 1
项,依此类推,并以BFS方式处理这些项。
我需要告诉池不接受超过level 2
个项目,以便有机会从worker_count
检索更高级别,以便以DFS方式处理项目。
我带来的当前解决方案是:对于每个提交的任务,将pqueue
对象保存在AsyncResult
列表中,然后在从asyncres_list
检索项目之前删除已处理的项目(如果有的话),检查pqueue
的长度是否每0.5秒低于池中的线程数,并且只会同时处理asyncres_list
个项目。
我想知道是否有更简洁的方法来实现此行为,我似乎无法在文档中找到一些参数来限制可以提交到池的最大任务数。
答案 0 :(得分:0)
ThreadPool
是一个简单的常见任务工具。如果您想自己管理队列,以获得DFS行为;您可以直接在顶级threading
和queue
模块上实现必要的功能。
为了防止安排下一个根任务,直到完成当前任务产生的所有任务(“DFS”式命令),你可以use Queue.join()
:
#!/usr/bin/env python3
import queue
import random
import threading
import time
def worker(q, multiplicity=5, maxlevel=3, lock=threading.Lock()):
for task in iter(q.get, None): # blocking get until None is received
try:
if len(task) < maxlevel:
for i in range(multiplicity):
q.put(task + str(i)) # schedule the next level
time.sleep(random.random()) # emulate some work
with lock:
print(task)
finally:
q.task_done()
worker_count = 2
q = queue.LifoQueue()
threads = [threading.Thread(target=worker, args=[q], daemon=True)
for _ in range(worker_count)]
for t in threads:
t.start()
for task in "01234": # populate the first level
q.put(task)
q.join() # block until all spawned tasks are done
for _ in threads: # signal workers to quit
q.put(None)
for t in threads: # wait until workers exit
t.join()
代码示例源自the queue
module documentation中的示例。
每个级别的任务会生成multiplicity
个直接子任务,这些任务会产生自己的子任务,直到达到maxlevel
。
None
用于向工人发出他们应该退出的信号。 t.join()
用于等待线程正常退出。如果主线程因任何原因被中断,那么除非有其他非守护程序线程,否则守护程序线程将被终止(您可能希望提供SIGINT hanlder,以通知工作者在Ctrl+C
上正常退出而不是仅仅死亡)
queue.LifoQueue()
来获得“后进先出”顺序(由于多个线程,它是近似值)。
maxsize
未设置,因为否则工作人员可能会死锁 - 无论如何,您必须将任务放在某处。无论任务队列如何,worker_count
后台线程都在运行。