Наконец, если вы хотите суммировать много чисел, вам не нужно сохранять их и суммировать позже. Вы можете суммировать их, как вы идете.

аюсь выполнить простой расчет (это вызываетMath.random() 10000000 раз). Удивительно, но запуск его простым способом выполняется намного быстрее, чем при использовании ExecutorService.

Я прочитал другую ветку наУдивительная точка безубыточности производительности ExecutorService - практические правила? и попытался последовать ответу, выполнивCallable используя партии, но производительность все еще плоха

Как улучшить производительность на основе моего текущего кода?

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;
        }
    }
}

Выход для этого кода

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

РЕДАКТИРОВАТЬ: производительность снижается из-за того, что Math.random () является синхронизированным методом .. после изменения Math.random () с новым объектом Random для каждого потока, производительность улучшилась

Вывод нового кода (после замены Math.random () на Random для каждого потока)

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

Ответы на вопрос(2)

Ваш ответ на вопрос