旧线程完成后如何启动新线程?


问题内容

我在列表中有一个很大的数据集,需要做一些工作。

我想在任意给定时间启动x数量的线程以在列表上工作,直到弹出该列表中的所有内容为止。

我知道如何在给定的时间(通过使用thread1 .... thread20.start())启动x数量的线程(说20个)

但是当前20个线程之一完成时,如何使它启动一个新线程?因此在任何给定时间,有20个线程在运行,直到列表为空。

我到目前为止所拥有的:

class queryData(threading.Thread):
    def __init__(self,threadID):
        threading.Thread.__init__(self)
        self.threadID = threadID
    def run(self):
        global lst
        #Get trade from list
        trade = lst.pop()
        tradeId=trade[0][1][:6]
        print tradeId


thread1 = queryData(1)
thread1.start()

更新资料

我的代码如下:

for i in range(20):
    threads.append(queryData(i))
for thread in threads:
    thread.start()

while len(lst)>0:
    for iter,thread in enumerate(threads):
        thread.join()
        lock.acquire()
        threads[iter] = queryData(i)
        threads[iter].start()
        lock.release()

现在它从头开始启动20个线程…然后在一个线程结束时继续启动一个新线程。

但是,它效率不高,因为它等待列表中的第一个完成,然后再等待第二个..依此类推。

有更好的方法吗?

基本上我需要:

-Start 20 threads:
-While list is not empty:
   -wait for 1 of the 20 threads to finish
   -reuse or start a new thread

问题答案:

正如我在评论中建议的那样,我认为使用amultiprocessing.pool.ThreadPool是合适的-
因为它可以自动处理许多您在代码中手动执行的线程管理。一旦所有线程都通过ThreadPoolapply_async()方法调用排队等待处理,唯一需要做的就是等待它们全部完成执行(当然,除非您的代码可以做其他事情)。

我已经将链接的答案中的代码翻译为另一个相关问题,因此它与您在使当前上下文中的内容易于理解时所执行的操作更加相似。

from multiprocessing.pool import ThreadPool
from random import randint
import threading
import time

MAX_THREADS = 5
print_lock = threading.Lock()  # Prevent overlapped printing from threads.

def query_data(trade):
    trade_id = trade[0][1][:6]
    time.sleep(randint(1, 3))  # Simulate variable working time for testing.
    with print_lock:
        print(trade_id)

def process_trades(trade_list):
    pool = ThreadPool(processes=MAX_THREADS)
    results = []
    while(trade_list):
        trade = trade_list.pop()
        results.append(pool.apply_async(query_data, (trade,)))

    pool.close()  # Done adding tasks.
    pool.join()  # Wait for all tasks to complete.

def test():
    trade_list = [[['abc', ('%06d' % id) + 'defghi']] for id in range(1, 101)]
    process_trades(trade_list)

if __name__ == "__main__":
    test()