ExecutorService的慢多线程性能 [英] ExecutorService slow multi thread performance

查看:203
本文介绍了ExecutorService的慢多线程性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图执行一个简单的计算(它调用 Math.random() 10000000次)。令人惊讶的是,使用简单方法运行它的速度比使用ExecutorService快得多。

I am trying to execute a simple calculation (it calls Math.random() 10000000 times). Surprisingly running it in simple method performs much faster than using ExecutorService.

我在 ExecutorService的令人惊讶的性能突破点 - 经验法则?,并试图通过执行可调用使用批次,但性能仍然不好

I have read another thread at ExecutorService's surprising performance break-even point --- rules of thumb? and tried to follow the answer by executing the Callable using batches, but the performance is still bad

如何根据我当前的代码提高性能?

How do I improve the performance based on my current code?

import java.util.*;
import java.util.concurrent.*;

public class MainTest {
    public static void main(String[]args) throws Exception {
        new MainTest().start();;
    }

    final List<Worker> workermulti = new ArrayList<Worker>();
    final List<Worker> workersingle = new ArrayList<Worker>();
    final int count=10000000;

    public void start() throws Exception {
        int n=2;

        workersingle.add(new Worker(1));
        for (int i=0;i<n;i++) {
            // worker will only do count/n job
            workermulti.add(new Worker(n));
        }

        ExecutorService serviceSingle = Executors.newSingleThreadExecutor();
        ExecutorService serviceMulti = Executors.newFixedThreadPool(n);
        long s,e;
        int tests=10;
        List<Long> simple = new ArrayList<Long>();
        List<Long> single = new ArrayList<Long>();
        List<Long> multi = new ArrayList<Long>();

        for (int i=0;i<tests;i++) {
            // simple
            s = System.currentTimeMillis();
            simple();
            e = System.currentTimeMillis();
            simple.add(e-s);

            // single thread
            s = System.currentTimeMillis();
               serviceSingle.invokeAll(workersingle); // single thread
            e = System.currentTimeMillis();
            single.add(e-s);

            // multi thread
            s = System.currentTimeMillis();
               serviceMulti.invokeAll(workermulti);
            e = System.currentTimeMillis();
            multi.add(e-s);
        }
        long avgSimple=sum(simple)/tests;
        long avgSingle=sum(single)/tests;
        long avgMulti=sum(multi)/tests;
        System.out.println("Average simple: "+avgSimple+" ms");
        System.out.println("Average single thread: "+avgSingle+" ms");
        System.out.println("Average multi thread: "+avgMulti+" ms");

        serviceSingle.shutdown();
        serviceMulti.shutdown();
    }

    long sum(List<Long> list) {
        long sum=0;
        for (long l : list) {
            sum+=l;
        }
        return sum;
    }

    private void simple() {
        for (int i=0;i<count;i++){
            Math.random();
        }
    }

    class Worker implements Callable<Void> {
        int n;

        public Worker(int n) {
            this.n=n;
        }

        @Override
        public Void call() throws Exception {
            // divide count with n to perform batch execution
            for (int i=0;i<(count/n);i++) {
                Math.random();
            }
            return null;
        }
    }
}

/ p>

The output for this code

Average simple: 920 ms
Average single thread: 1034 ms
Average multi thread: 1393 ms

编辑:性能受到Math.random()是一种同步方法的影响..改变Math.random )用每个线程的新的Random对象,性能提高

performance suffer due to Math.random() being a synchronised method.. after changing Math.random() with new Random object for each thread, the performance improved

新代码的输出(用每个线程的Random替换Math.random()之后)

The output for the new code (after replacing Math.random() with Random for each thread)

Average simple: 928 ms
Average single thread: 1046 ms
Average multi thread: 642 ms


推荐答案

Math.random()同步。同步的整个点的种类是慢下来,所以他们不会碰撞。使用不同步的东西和/或给每个线程自己的对象工作,像一个新的随机

Math.random() is synchronized. Kind of the whole point of synchronized is to slow things down so they don't collide. Use something that isn't synchronized and/or give each thread its own object to work with, like a new Random.

这篇关于ExecutorService的慢多线程性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆