【发布时间】:2015-01-18 03:11:05
【问题描述】:
我试图弄清楚如何从多线程应用程序中获得最大性能。
我有一个这样创建的线程池:
ExecutorService executor = Executors.newFixedThreadPool(8); // I have 8 CPU cores.
我的问题是,我应该将工作分成 8 个可运行/可调用对象,这与线程池中的线程数相同,还是应该将其分成 1000000 个可运行对象/可调用对象?
for (int i = 0; i < 1000000; i++)
{
Callable<Long> worker = new MyCallable(); // Each worker does little work.
Future<Long> submit = executor.submit(worker);
}
long sum = 0;
for (Future<Long> future : list)
sum += future.get(); // Much more overhead from the for loops
或
for (int i = 0; i < 8; i++)
{
Callable<Long> worker = new MyCallable(); // Each worker does much more work.
Future<Long> submit = executor.submit(worker);
}
long sum = 0;
for (Future<Long> future : list)
sum += future.get(); // Negligible overhead from the for loops
划分为 1000000 个可调用对象对我来说似乎更慢,因为实例化所有这些可调用对象并在 for 循环中从它们收集结果会产生开销。另一方面,如果我有 8 个可调用对象,则此开销可以忽略不计。而且由于我只有 8 个线程,我不能同时运行 1000000 个可调用对象,因此没有性能提升。
我是对还是错?
顺便说一句,我可以测试这些情况,但操作非常简单,我猜编译器意识到了这一点并进行了一些优化。所以结果可能会产生误导。我想知道哪种方法更适合图像处理应用。
【问题讨论】:
-
第二种方法更好恕我直言,开销也是用户级线程的一个因素
-
如果您将 1000000 个工作单元划分为 8 个可运行文件,您最终不会得到某种队列,其中每个可运行文件都有 N/8 个项目吗?这与一开始就拥有所有这些 N 个可运行文件不一样吗(除了你现在有一个两层工作队列)?
-
不是真正的两层,因为我的整个工作都是 N*W。 (N 是 runnable 的数量,W 是每个 runnable 所做的工作。)如果我将 N 减少到 8,我将相应地增加 W。我仍然可以在一个可运行的整体中完成 W 数量的工作。但是如果我的 N 是 1000000,我必须创建那么多可运行对象并从所有这些可运行对象中收集结果。
-
@Utku:那是两层。您可以为每个工作单元创建一个 Runnable,并且只有一个队列(由 ExecutorService 为您管理)。
标签: java multithreading performance concurrency threadpool