java - 多线程中的简单计算比单线程需要更长的时间

时间:2015-01-14 11:04:28

标签: java multithreading performance

我试图了解如何利用多线程。我写了一个简单的程序,增加i的值,让我们说,使用两种方式400,000次:单线程方式(0到400,000)和多线程方式(在我的情况下,4次) :0到100,000),线程数等于Runtime.getRuntime().availableProcessors()

我对我测量的结果感到惊讶:单线程方式明显更快,有时快3倍。这是我的代码:

public class Main {
    public static int LOOPS = 100000;
    private static ExecutorService executor=null;

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        int procNb = Runtime.getRuntime().availableProcessors();
        long startTime;
        long endTime;

        executor = Executors.newFixedThreadPool(procNb);
        ArrayList<Calculation> c = new ArrayList<Calculation>();

        for (int i=0;i<procNb;i++){
            c.add(new Calculation());
        }

        // Make parallel computations (4 in my case)
        startTime = System.currentTimeMillis();
        queryAll(c);
        endTime = System.currentTimeMillis();

        System.out.println("Computation time using " + procNb + " threads : " + (endTime - startTime) + "ms");

        startTime = System.currentTimeMillis();
        for (int i =0;i<procNb*LOOPS;i++)
        {

        }
        endTime = System.currentTimeMillis();
        System.out.println("Computation time using main thread : " + (endTime - startTime) + "ms");
    }

    public static List<Integer> queryAll(List<Calculation> queries) throws InterruptedException, ExecutionException {
        List<Future<Integer>> futures = executor.invokeAll(queries);
        List<Integer> aggregatedResults = new ArrayList<Integer>();
        for (Future<Integer> future : futures) {
            aggregatedResults.add(future.get());
        }
        return aggregatedResults;
    }

}

class Calculation implements Callable<Integer> {

    @Override
    public Integer call() {
        int i;
        for (i=0;i<Main.LOOPS;i++){
        }
        return i;
    }
}

控制台:

Computation time using 4 threads : 10ms. Computation time using main thread : 3ms.

有人能解释一下吗?

1 个答案:

答案 0 :(得分:8)

添加可能需要一个cpu周期,所以如果你的cpu以3GHz运行,那就是0.3纳秒。做它400k次,变成120k纳秒或0.1毫秒。因此,您的测量更多地受到启动线程,线程切换,JIT编译等的开销的影响,而不是您尝试测量的操作。

您还需要考虑编译器优化:如果将空循环放在方法中并多次运行该方法,您会注意到它在一段时间后在0毫秒内运行。因为编译器确定循环什么也不做,并完全优化它。

我建议您使用专门的库进行微基准测试,例如jmh

另请参阅:How do I write a correct micro-benchmark in Java?