我现在一直在玩多处理,有些东西让我感到困惑。 我写了这个简单的代码来说明问题:
from multiprocessing.pool import ThreadPool #I import the packages needed
from time import sleep
def long_task(n): #a simple long task
sleep(1)
print str(n)+" task finished"
pool = ThreadPool(8) #define my threadpool
for x in xrange(10**7): #it could be a while loop too
print x
pool.apply_async(long_task, args=(x,))
在for
循环内部我希望我的代码等到8个线程中的一个完成后再启动另一个,但是x
正在打印而没有任何中断。
为什么会这样?我如何得到我正在寻找的东西?这段代码是否经过优化?
示例输出:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
答案 0 :(得分:1)
您遇到的部分困惑是您正在尝试启动10**7
任务。为了实验,将其减少到一些合理的数字,比如说30
。您的输出现在是
0
1
2
...
27
28
29
然后,大约一秒钟之后,类似
2 task finished3 task finished
0 task finished1 task finished
5 task finished4 task finished6 task finished
7 task finished
文本将全部乱码,在我的情况下,换行符通常分批打印。这是因为对print
的调用未正确同步。下一批将在大约一秒后打印出来:
13 task finished
11 task finished9 task finished8 task finished12 task finished
10 task finished
类似于第三批。最后一批只包含最后6个输出(24-30):
24 task finished
25 task finished
26 task finished
29 task finished27 task finished
28 task finished
要记住的是,任务立即计划。这是线程池的目的。这意味着它们只会被添加到稍后运行的事物列表中,这就是您立即看到x
打印输出的原因。正如您所料,这些任务实际上一次运行八个。实际上,第一批之后的任务是在线程可用时逐个启动的,但由于它们几乎完全相同的时间,看起来好像它们是批量运行。
你可以设置一个实验来看看当你的一半任务需要1秒钟运行而一半需要2秒时会发生什么。虽然它们将按照您将它们添加到队列的顺序立即启动,但1秒任务的线程将比2秒任务的线程快两倍。