2016-08-22 26 views
0

在我用python编写的软件代码的一部分中,我有一个项目列表,其大小可以从12变化到仅一个项目。对于这个列表中的每个项目,我正在做一些处理(发送与给定项目相关的HTTP请求,解析结果和许多其他操作。我想使用线程加速我的代码,我想创建2个线程其中每一个采取了一些项目,并做处理异步如何根据数字添加线程

例1:比方说,在我的名单上有12个项目,每个线程将采取在这种情况下,6个项目,并呼吁各处理功能项目

例2:现在让我们说,我的名单有9个项目,一个线程将采取5项和其他线程将采取其他4个项目留下

目前我未施加任何线程和我的代码库是非常大的,所以这里的一些代码,做几乎同样的事情,我的情况:

#This procedure need to be used with threading . 
itemList = getItems() #This function return an unknown number of items between 1 and 12 

if len(itemList) > 0: # Make sure that the list is empty in this case . 
    for item in itemList: 
     processItem(item) #This is an imaginary function that do the processing on each item 

下面是解释什么是基本的精简版代码我我不知道怎样才能使我的线程更具灵活性,因此每个人都需要一些项目,其他人则需要休息(如示例1 & 2中所述)。

感谢的您的时间

+0

调查线程执行者。用两个线程启动一个执行器,并将所有项目提交给它。这样做的好处是为您做好所有的簿记工作,并确定哪个线程应该采取下一项工作,以保持最大程度的繁忙。 –

回答

2

你可能会使用共享队列 https://docs.python.org/3/library/queue.html#queue-objects

import queue 
import threading 

def worker(): 
    while True: 
     item = q.get() 
     if item is None: 
      break 
     do_work(item) 
     q.task_done() 

q = queue.Queue() 
threads = [] 
for i in range(num_worker_threads): 
    t = threading.Thread(target=worker) 
    t.start() 
    threads.append(t) 

for item in source(): 
    q.put(item) 

# block until all tasks are done 
q.join() 

# stop workers 
for i in range(num_worker_threads): 
    q.put(None) 
for t in threads: 
    t.join() 

https://docs.python.org/3/library/queue.html#module-queue报价,而实现它:

队列模块实现多生产,多消费者队列。它 是特别有用的线程编程时,信息必须在多个线程之间安全地交换 。

这个想法是,你有一个共享存储,每个线程尝试从它逐一读取项目。 这比预先分配负载要灵活得多,因为您不知道操作系统将如何计划线程执行,每次迭代需要多少时间等。 此外,您可能会将项目添加到此队列动态 - 例如,有一个生产者线程并行运行。

一些有用的链接:

简单的介绍到并行编程的Python:在生产者 - 消费者模式 http://www.slideshare.net/dabeaz/an-introduction-to-python-concurrency

更多细节与行由行解释: http://www.informit.com/articles/article.aspx?p=1850445&seqNum=8

+0

这正是我要建议的,但你更快:-)。 – pts

+0

这段代码的一些解释。所有待处理的工作项都在“队列”中。工作者线程不知道他们要处理多少项目。他们一个接一个地处理项目,直到最后(“无”)。 – pts

+0

非常感谢您的意见,但我对线程很陌生,我很乐意为您解释您的代码或添加一些对其他新手更好理解的评论。 –

1

你可以使用Python 3中的concurrent.futures模块的ThreadPoolExecutor类。该模块在Python 2中不存在,但有一些解决方法(我不会讨论)。

线程池执行程序基本上完成了@ffeast提出的任务,但只需要编写更少的代码行。它管理着一个线程池,它将执行你提交给它的所有任务,大概是以最有效的方式。结果将通过Future对象返回,这表示“未决”结果。

既然您似乎知道预先列出的任务,这对您来说尤其方便。虽然你不能保证任务如何在线程之间被分割,但结果可能至少和你手工编写的任何东西一样好。

from concurrent.futures import ThreadPoolExecutor 
with ThreadPoolExecutor(max_workers=2) as executor: 
    for item in getItems(): 
     executor.submit(processItem, item) 

如果您需要输出更多的信息,比如识别已经完成或取得结果从他们的期货的一些方法,请参见Python文档中的example(在其上面的代码在很大程度上依赖) 。