任务队列大小

时间:2016-10-28 10:28:27

标签: python multithreading python-3.x threadpool python-multiprocessing

我的问题如下:我有multiprocessing.pool.ThreadPoolworker_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个项目。

我想知道是否有更简洁的方法来实现此行为,我似乎无法在文档中找到一些参数来限制可以提交到池的最大任务数。

1 个答案:

答案 0 :(得分:0)

ThreadPool是一个简单的常见任务工具。如果您想自己管理队列,以获得DFS行为;您可以直接在顶级threadingqueue模块上实现必要的功能。

为了防止安排下一个根任务,直到完成当前任务产生的所有任务(“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后台线程都在运行。