【发布时间】:2010-12-11 12:05:57
【问题描述】:
我正在尝试弄清楚如何正确使用 Java 的 Executors。我意识到向ExecutorService 提交任务有其自身的开销。但是,看到它这么高,我很惊讶。
我的程序需要以尽可能低的延迟处理大量数据(股市数据)。大多数计算都是相当简单的算术运算。
我尝试测试一些非常简单的东西:“Math.random() * Math.random()”
最简单的测试在一个简单的循环中运行此计算。第二个测试在匿名 Runnable 中执行相同的计算(这应该衡量创建新对象的成本)。第三个测试将Runnable 传递给ExecutorService(这衡量了引入执行者的成本)。
我在我的小笔记本电脑(2 cpu,1.5 gig ram)上运行了测试:
(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422
(大约有四次运行,前两个数字最终相等)
请注意,执行程序比在单个线程上执行花费的时间要多得多。线程池大小在 1 到 8 之间的数字大致相同。
问题:我是否遗漏了一些明显的东西或者这些结果是预期的?这些结果告诉我,我传递给执行程序的任何任务都必须进行一些重要的计算。如果我正在处理数百万条消息,并且我需要对每条消息执行非常简单(且成本低廉)的转换,我仍然可能无法使用执行器......尝试将计算分布在多个 CPU 上可能最终会比仅仅花费更多在一个线程中执行它们。设计决策变得比我最初想象的要复杂得多。有什么想法吗?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecServicePerformance {
private static int count = 100000;
public static void main(String[] args) throws InterruptedException {
//warmup
simpleCompuation();
computationWithObjCreation();
computationWithObjCreationAndExecutors();
long start = System.currentTimeMillis();
simpleCompuation();
long stop = System.currentTimeMillis();
System.out.println("simpleCompuation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreation();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreationAndExecutors();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreationAndExecutors:"+(stop-start));
}
private static void computationWithObjCreation() {
for(int i=0;i<count;i++){
new Runnable(){
@Override
public void run() {
double x = Math.random()*Math.random();
}
}.run();
}
}
private static void simpleCompuation() {
for(int i=0;i<count;i++){
double x = Math.random()*Math.random();
}
}
private static void computationWithObjCreationAndExecutors()
throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(1);
for(int i=0;i<count;i++){
es.submit(new Runnable() {
@Override
public void run() {
double x = Math.random()*Math.random();
}
});
}
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
}
}
【问题讨论】:
-
哇,预览格式化的代码比最终结果好得多。我该如何解决这个问题?
-
我刚刚重新格式化了,看起来更好吗?
-
感谢 ZZ Coder,代码现在看起来应该是这样的
-
是的,我没有运行任何这些代码示例,但我强烈怀疑上面运行的 ExecutorService 中几乎所有时间都来自 ExecutorService 的创建,甚至可能在为其工作产生一个新线程。
-
不,服务和线程的创建是微不足道的。时间是由于锁定了 Math.random。
标签: java performance executorservice