python 线程池不等待进程结束

python threadpool not waiting for process to end

我玩多处理已经有一段时间了,有些事情让我很困惑。 我写了这个简单的代码来说明问题:

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

您感到困惑的部分原因是您正在尝试启动 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 秒任务线程的两倍。