Почему служба исполнителя занимает больше времени, чем последовательная операция в Java 8?

#java #multithreading #concurrency

#java #многопоточность #параллелизм

Вопрос:

В следующей программе я хочу отсортировать 4 разных массива параллельно, поэтому использовал ExecutorService для создания FixedThreadPool размером 4 (количество доступных процессоров). Я предполагаю, что это займет меньше времени по сравнению с последовательной операцией, но я вижу, что последовательная операция выполняется быстрее. Здесь нужна какая-либо дальнейшая оптимизация?

Вот код:

 public class ThreadFoolOptimumSize {

private static int data1[] = new int[10000];
private static int data2[] = new int[20000];
private static int data3[] = new int[10000];
private static int data4[] = new int[30000];

public static void main(String ars[]) {
    long startTime = System.currentTimeMillis();
    int processors_count = Runtime.getRuntime().availableProcessors();
    System.out.println(processors_count);
    Random random = new Random();
    data1 = random.ints(10000, 10, 10000).toArray();
    data2 = random.ints(20000, 10, 20000).toArray();
    data3 = random.ints(10000, 10, 10000).toArray();
    data4 = random.ints(30000, 10, 30000).toArray();

    ExecutorService executorService = Executors.newFixedThreadPool(processors_count);
    executorService.execute(new Runnable() {
        public void run() {
            Arrays.sort(data1);
            System.out.println("sorted data1:");
            System.out.println(Arrays.toString(data1));
        }
    });

    executorService.execute(new Runnable() {
        public void run() {
            Arrays.sort(data2);
            System.out.println("sorted data2:");
            System.out.println(Arrays.toString(data2));
        }
    });

    executorService.execute(new Runnable() {
        public void run() {
            Arrays.sort(data3);
            System.out.println("sorted data3:");
            System.out.println(Arrays.toString(data3));
        }
    });

    executorService.execute(new Runnable() {
        public void run() {
            Arrays.sort(data4);
            System.out.println("sorted data4:");
            System.out.println(Arrays.toString(data4));
        }
    });

    executorService.shutdown();

    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            long endTime = System.currentTimeMillis();
            System.out.println("Total:"   (endTime-startTime)   " ms");
        }
    });
}
  

}

Комментарии:

1. Вы создаете processors_count потоки, но для запуска основного потока требуется ядро процессора. И для запуска операционной системы требуется хотя бы одно ядро. Кроме того, мне было бы интересно, использует ли ваша последовательная версия перехват завершения работы для вычисления прошедшего времени.

Ответ №1:

Я повторил ваш тест и подтверждаю ваше наблюдение: я просто думаю, что настройка службы Executor требует затрат, я провел несколько дополнительных тестов на ноутбуке с 8 ядрами, и даже увеличив все массивы в десять раз, я все равно получаю стандартную версию быстрее.

Увеличение еще в десять раз (таким образом, размеры порядка миллионов) Я, наконец, заставляю исполнителя работать быстрее.

Таким образом, очевидно, что вопрос о том, сколько данных вам нужно обработать, в некоторых случаях не стоит использовать исполнителя. (Конечно, я прокомментировал распечатку отсортированных массивов).

Кроме того, добавьте, что использование разных размеров массивов делает разницу менее заметной: вначале вы сортируете 4 массива параллельно, через 1/3 времени вы выполняете 2 сортировки, data1 и data3, и продолжаете обрабатывать параллельно два других, data2 и data4, и последнюю треть времени вы обрабатываете один массив, data4. Если вы отсортируете идентичные массивы, выигрыш в скорости будет более очевидным.

Наконец, позвольте мне добавить, что измеренное время сильно колеблется, вам нужно повторить его несколько раз и усреднить, чтобы получить стабильное число и выполнить надлежащий тест. При размерах в несколько 100 000 с время колеблется на целых 50% на моем ноутбуке.