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

Posted

技术标签:

【中文标题】java - 多线程中的简单计算比单线程中需要更长的时间【英文标题】:java - Simple calculation takes longer in multi threads than in single thread 【发布时间】:2015-03-12 13:05:33 【问题描述】:

我正在尝试了解如何利用多线程。我编写了一个简单的程序,它使用两种方式将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.

谁能解释一下?

【问题讨论】:

你不觉得你在多线程中做的太多了吗?创建未来,将未来添加到列表中?此外,多线程总是比单线程更好也不是强制性的。 我猜创建多个线程比增加值花费的时间更长。 当然多线程有开销。你需要一个足够大的问题来获得多线程的优势。它还取决于平台、硬件(多核)和使用的实现(Java8 Streams 可以大量使用多核)。 另外,为了加快使用多线程的速度,一个线程的计算不能依赖或阻塞另一个线程的计算结果。 【参考方案1】:

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

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

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

另见:How do I write a correct micro-benchmark in Java?

【讨论】:

感谢您的回答。即使我将循环数乘以十,结果也是一样的。我认为强调我的“for”循环为空也很重要,编译器优化了它的计算......而且我的基准测试有偏差!

以上是关于java - 多线程中的简单计算比单线程中需要更长的时间的主要内容,如果未能解决你的问题,请参考以下文章

c#中Timer是单线程还是多线程

多线程比单线程慢

多线程多锁似乎比单锁慢

java多线程编程

Java多线程编程

多线程函数性能比单线程差