【发布时间】:2023-03-05 09:50:01
【问题描述】:
所以我编写了一个工具,它获取项目列表,将其拆分为给定数量的列表(比如说 10 个),然后取出这 10 个列表并产生 10 个线程,“EvaluationThreads”(扩展 threading.thread) ,并且这些线程中的每一个都会评估它们提供给评估的任何内容。当我启动每个线程时,我将它们全部放入一个列表中,在生成它们之后,我有以下代码:
for th in threadList:
th.join()
someTotal = th.resultsAttribute
这就是我如何等待所有线程完成并收集它们的信息。虽然这是一种等待一切完成然后收集结果的工作方式,但我觉得必须有一种更优雅的方式来做这件事,因为这些线程可以很好地在不同的时间完成,如果第一个开始的线程最后完成所有较早完成的必须等待该线程完成才能加入。有没有办法获取这些线程的信息并在它们完成时加入它们,而不是按照它们开始的顺序?我最初认为我会在线程中使用某种回调或其他东西,但我不确定是否有更可接受的解决方案。
感谢您的帮助。
编辑:澄清一下,我的评估函数不受 CPU 限制,我并没有尝试在线程之间分配文档以尽快完成,每个线程都有固定的大约偶数个作业。
【问题讨论】:
-
为什么您的问题有问题?一个已完成但尚未加入的线程浪费了很少的资源(基本上,在内核或用户空间某处由操作系统维护的表中的一个小条目)。
-
我想这不完全是一个问题,但它似乎是一个非常不优雅的解决方案,如果空闲线程不是等待加入的问题,我想我不会担心它。
-
附注:如果您的“评估”操作受 CPU 限制,那么在此应用程序中使用线程可能不会给您带来太多好处。了解 CPython 的全局解释器锁 (GIL)。
-
@NedBatchelder:对此+1。如果数据块复制起来很便宜(或者可以由线程本身生成而不是传入),那么使用多处理而不是线程可能会更好。这也意味着默认情况下数据是不共享的(所以如果你搞砸了,它既更明显也更不那么灾难性)。并且 multiprocessing 有一个内置的 Pool 类,有很好的方法来简化最常见的习惯用法。
-
他们甚至不是空闲线程;它们是完整的线程。尽快加入他们很好,但这意味着您需要某种方式来知道需要先加入哪个。 (或者你需要一个与 Win32 的 WaitForMultipleObjects 等效的跨平台,而你没有……尽管一个像样的线程组/池库可能会使用每个平台上可用的最佳实现。)
标签: python multithreading join spawn