-3

我的情况是我有 4 组,每组 7 个线程。我的 CPU(核心 i7)应该能够处理 8 个线程,所以我正在考虑一次通过每个组,运行 7 个线程,然后移动到第二组,运行它的 7 个线程,然后是第三和第 4 组以同样的方式,然后从第 1 组开始,直到用户发出停止命令。

我的问题是,一旦每组 7 个线程完成处理,我应该让这些线程空闲,还是完全关闭它们并在下一次迭代时重新启动一组新的 7 个线程?哪种方法会更快?这是一个速度非常密集的应用程序,所以我需要一切都尽快发生。

我将使用 aFixedThreadPool来管理每组 7 个线程。所以我可以只是invokeAll()然后不理会它们(大概是空闲的),或者我可以shutdown()在每个invokeAll()线程池之后在下一次迭代中启动一个新的线程池。

哪种方法会更快?

4

4 回答 4

4

我的问题是,一旦每组 7 个线程完成一个处理周期,我应该让这些线程空闲,还是完全关闭它们并在下一个周期重新启动一组新的 7 个线程?

我将使用单个ExecutorService线程池并为所有任务重用相同的线程。请参阅有关该主题的教程。线程池旨在执行任何RunnableCallable类,因此它们与任务无关。例如,您可能有 ParentResultChildResult类。您可以将 a 提交Callable<ParentResult>到将返回 a 的线程池,Future<ParentResult> 可以将 a 提交Callable<ChildResult>到将返回 a 的同一线程池Future<ChildResult>

您想要拥有“线程组”的唯一原因是每个线程都有一些它必须维护的状态——数据库连接或其他东西。即便如此,很多人还是使用线程池,因为它为您完成了大部分并发繁重的工作。

如果您确实必须保持此状态,那么我当然不会关闭池,然后再重新启动它们。休眠线程/池除了内存之外没有占用任何系统资源。您这样做的唯一原因是,如果您为任务分叉了 100 个线程,但此时,您应该考虑重新构建您的应用程序。

于 2013-10-07T15:07:31.723 回答
1

您无需手动安排线程。一次启动所有 28 个线程 - 这不会更慢,但可以更快。

于 2013-10-07T16:58:30.723 回答
1

当你说你的处理器有 8 个线程时,我认为你的意思是它有 4 个带有超线程的内核。Java 使用的线程与您的处理器不同,因此这 7 个线程的类型与您的处理器不同。

JVM 处理处理器使用情况,并且 (IIRC) 仅限于使用 1 个内核。java 使用的线程特定于 JVM,并且是完全独立的。

至于您的实际问题,请尝试测试不同的线程组合以查看哪个最快,这将为您提供比扶手椅理论更准确的答案。

于 2013-10-07T15:15:39.663 回答
0

我也更喜欢Alexei Kaigorodov建议启动所有 28 个线程。但我建议您newFixedThreadPool用新的Executors API 替换:(从 Java 8 开始)

static ExecutorService  newWorkStealingPool()

创建一个工作窃取线程池,使用所有可用处理器作为其目标并行度级别。

以上 API 返回ForkJoinPool类型ExecutorService

现在您无需担心空闲线程的使用。Java 将通过工作窃取机制更好地利用空闲线程。

如果您仍然需要四组不同的 FixedThreadPools,您可以继续使用invokeAll. 不要关闭 ExecutorService 在多个池之间切换。你一个ExecutorService有效的。如果要使用 invokeAll 轮询 Future 任务的结果,使用CompletableFuture并轮询它以了解任务执行的状态。

static CompletableFuture<Void>  runAsync(Runnable runnable, Executor executor)

返回一个新的 CompletableFuture,它在运行给定操作后由给定执行程序中运行的任务异步完成。

于 2016-03-14T23:31:29.177 回答