【发布时间】:2014-07-09 14:34:05
【问题描述】:
我正在玩 Java(Sun JDK 1.7 64 位)中的多线程,试图更好地掌握一些概念。 我发现令人费解的是找到执行程序的线程池大小以及该设置对性能的影响。这是我的基本代码:
public class Program {
static int bestThreads = 0;
static long bestTime = Integer.MAX_VALUE;
public static void main(String[] args) throws InterruptedException, ExecutionException {
int cores = Runtime.getRuntime().availableProcessors();
for (int sizeOfPool = 1; sizeOfPool <= cores; sizeOfPool++) {
ExecutorService exec = Executors.newFixedThreadPool(sizeOfPool);
//System.out.println("Started");
int noOftasks = 1000;
for (int i = 0; i < noOftasks; i++) {
Calculator c = new Calculator();
exec.submit(c);
}
long start = System.currentTimeMillis();
exec.shutdown();
exec.awaitTermination(1000, TimeUnit.DAYS);
long stop = (System.currentTimeMillis() - start);
//System.out.println("Done " + noOftasks + " tasks in " + stop + " on " + sizeOfPool + " threads");
if (bestTime > stop) {
bestTime = stop;
bestThreads = sizeOfPool;
}
}
System.out.println("Best size of pool " + bestThreads + " result in " + bestTime + " ms");
}
public static class Calculator implements Runnable {
@Override
public void run() {
doJob();
}
}
//Can be whatever this just gives me a few milliseconds worth of CPU load since I don't want to use Thread.sleep()
public static void doJob() {
for (int j = 0; j < 1E3; j++) {
Math.round(Math.sin(Math.sqrt(Math.random())));
}
}
当我运行这个程序时,我发现使用最少时间的设置是使用 N 个线程的设置,其中 N 通常为 2(这意味着我应该使用 2 个线程作为我的线程池的大小)。 我不明白为什么会发生这种情况,因为我从 .availableProcessors() 获得的处理器数量为 4(我使用 i3 和多线程,它在笔记本电脑上,Windows 显示运行程序时所有线程都处于活动状态)。 此外,当我更改完成的工作量时,我通常会得到不同的结果:
1E1 -> N=4
1E2 -> N=3 或 2
1E3 -> N=2
1E4 -> N=2
但即便如此,在大多数情况下我还是得到 N=2;
谁能解释一下为什么我会得到这样的结果,以及通常建议的池大小取决于程序运行的 CPU。
这里还有一些我觉得奇怪的输出:
在 1 个线程上完成 195 个任务 1000 个任务//好吧,这个处理器需要大约 200 毫秒才能完成这项工作,我想超频会有所帮助
在 2 个线程上完成 134 个任务中的 1000 个任务 //我知道由于上下文切换和线程创建开销的一些其他影响,我无法获得 2 倍的增长,但这是一个很好的加速
在3个线程上完成138个任务1000个//几乎和2个线程一样,为什么没有更糟或更好
在 210 个线程上完成 1000 个任务,4 个线程//比 1 个线程更糟糕,这是我真的不明白的一个
【问题讨论】:
标签: java multithreading cpu multicore