如何管理python线程结果?

如何管理python线程结果?,python,multithreading,arrays,Python,Multithreading,Arrays,我正在使用以下代码: def startThreads(arrayofkeywords): global i i = 0 while len(arrayofkeywords): try: if i<maxThreads: keyword = arrayofkeywords.pop(0) i = i+1 thread = doStuf

我正在使用以下代码:

def startThreads(arrayofkeywords):
    global i
    i = 0
    while len(arrayofkeywords):
        try:
            if i<maxThreads:
                keyword = arrayofkeywords.pop(0)
                i = i+1
                thread = doStuffWith(keyword)
                thread.start()
        except KeyboardInterrupt:
            sys.exit()
    thread.join()
def startThreads(arrayofkeywords):
全球i
i=0
而len(arrayofkeywords):
尝试:

如果i您需要保留指向所生成的每个线程的指针。按原样,您的代码只确保最后创建的线程完成。这并不意味着在它之前开始的所有项目都已经完成

def startThreads(arrayofkeywords):
    global i
    i = 0
    threads = []
    while len(arrayofkeywords):
        try:
            if i<maxThreads:
                keyword = arrayofkeywords.pop(0)
                i = i+1
                thread = doStuffWith(keyword)
                thread.start()
                threads.append(thread)
        except KeyboardInterrupt:
            sys.exit()
    for t in threads:
        t.join()
    //process results stored in each thread
def startThreads(arrayofkeywords):
全球i
i=0
线程=[]
而len(arrayofkeywords):
尝试:

if i如果使用信号量来保护关键部分,那么写入全局数组就可以了。要附加到全局数组时,可以“获取”锁,完成后再“释放”。这样,每个线程只有一个附加到数组中

查看并搜索信号灯以获取更多信息

sem = threading.Semaphore()
...
sem.acquire()
# do dangerous stuff
sem.release()
使用本质上是线程安全的实例。每个线程都可以
。完成后将其结果放入该全局实例,主线程(当它知道所有工作线程都完成时,通过
。加入
,例如在@unholysampler的回答中加入它们)可以循环
。从中获取
,并使用每个结果
。扩展
“总体结果”列表,直到队列清空

编辑:您的代码还有其他大问题——如果最大线程数小于关键字数,它将永远不会终止(您尝试为每个关键字启动一个线程——永远不会减少——但是如果您已经启动了最大线程数,则将永远循环,不再重复)

考虑使用一个线程池,有点像中的线程池,不同的是,在对可调用项进行排队时,您将对关键字进行排队——因为您希望在线程中运行的可调用项在每个线程中都是相同的,只需改变参数即可。当然,callable将被更改为从传入任务队列中剥离某些内容(使用
.get
)和
。完成后将结果列表放入传出结果队列

要终止N个线程,您可以在所有关键字之后,
.put
N“sentinels”(例如,
None
,假设没有关键字可以是
None
):如果线程刚才拉取的“关键字”是
None
,则线程的可调用项将退出


通常情况下,
Queue.Queue
提供了用Python组织线程(和多处理!)体系结构的最佳方法,无论它们是我指给您的配方中的通用体系结构,还是我在最后两段中为您的用例建议的更专业的体系结构。

尝试一些信号量方法,如acquire和release。。

首先,您实际上需要保存所有那些
thread
对象,以便对它们调用
join()
。如前所述,您只保存最后一个,并且只有在没有异常的情况下才保存

执行多线程编程的一种简单方法是为每个线程提供它运行所需的所有数据,然后让它不向该工作集之外的任何对象写入数据。如果所有线程都遵循该准则,那么它们的写操作将不会相互干扰。然后,一旦一个线程完成,让主线程只将结果聚合到一个全局数组中。这就是所谓的“fork/join并行性”

如果对Thread对象进行子类化,则可以为它提供存储该返回值的空间,而不会干扰其他线程。然后你可以这样做:

class MyThread(threading.Thread):
    def __init__(self, ...):
        self.result = []
        ...

def main():
    # doStuffWith() returns a MyThread instance
    threads = [ doStuffWith(k).start() for k in arrayofkeywords[:maxThreads] ]
    for t in threads:
        t.join()
        ret = t.result
        # process return value here
编辑:

环顾四周,似乎是上面的方法。以上是一种Java风格的线程模式。相反,您可以执行以下操作:

def handler(outList)
    ...
    # Modify existing object (important!)
    outList.append(1)
    ...

def doStuffWith(keyword):
    ...
    result = []
    thread = Thread(target=handler, args=(result,))
    return (thread, result)

def main():
    threads = [ doStuffWith(k) for k in arrayofkeywords[:maxThreads] ]
    for t in threads:
        t[0].start()
    for t in threads:
        t[0].join()
        ret = t[1]
        # process return value here

我知道这个问题有点老了,但最好的办法是不要像其他同事提出的那样对自己造成太大伤害:)

请阅读上的参考资料。这样,您就可以参与您的工作:

def doStuffWith(keyword):
    return keyword + ' processed in thread'

def startThreads(arrayofkeywords):
    pool = Pool(processes=maxThreads)
    result = pool.map(doStuffWith, arrayofkeywords)
    print result

我如何访问每个线程的本地数据?因为线程一直都在创建/完成,不像10个线程总是一样。根据本地数据,我指的是Karmastan的解决方案。根据您在问题中发布的内容,看起来您创建了N个线程,然后开始,然后加入它们。假设在线程结束后访问本地数据的模式可以正常工作。如果您想让事情变得更加动态,那么您需要查看讨论线程池和将结果存储在数据队列中的答案。谢谢,您的答案对我来说是最容易理解的,我现在就试试。值得注意的是,
Pool
使用
多处理
而不是
线程
,它为每个进程使用单独的内存空间,因此比线程慢。使用multiprocessing.pool import ThreadPool
中的
作为线程等效的