2016-06-15 6 views
3
ExecutorService threadPool = Executors.newFixedThreadPool(N); 

for (Runnable task : tasks) { 
    threadPool.execute(task); 
} 

Я немного новичок в многопоточности. Это вопрос, который я получил в недавнем интервью. Может кто-то помочь мне с решением и ясным объяснением. В приведенном выше коде каждая задача тратит 25% времени на вычисление и 75% времени на ввод-вывод. Предполагая четырехъядерную машину (без гиперпоточности), каков должен быть размер пула потоков N для достижения оптимальной производительности без потери потоков, предполагающих бесконечную пропускную способность ввода-вывода.Исполнитель пула приложений в Java

ответ

1

Если ваша машина имеет бесконечный ввод-вывод, это означает, что вы можете полностью сосредоточиться на процессорах. Каждая задача использует четверть процессора во время работы. Это означает, что вы можете выполнить четыре задачи для насыщения одного ядра ЦП и сделать N = 16 на четырехъядерном процессоре.

Это, однако, чисто теоретический ответ. В действительности вы найдете несколько проблем, почему N = 16 может быть слишком большим или слишком маленьким. В качестве примера предположим, что все 16 задач идентичны в их планировании (CPU против IO) и запускаются в тот же момент. Это означало бы, что в первом процессоре интенсивная временная шкала исполнения-скорости сводится к одной четверти (16 потоков борются за четыре процессора). Кроме того, можно было бы предположить, что требуется некоторая загрузка процессора для запуска ОС, планировщика, сбора мусора и тому подобного. Это сделало бы N = 16 слишком большим.

С другой стороны, если для каждой задачи не требуется работать с максимальной индивидуальной скоростью, больший N может дать вам лучшую общую производительность, например, если в определенный временной интервал более 3/4 потоков делает I/O, это оставило бы ресурсы CPU неиспользованными в тот самый момент.

Я предполагаю, что это не вопрос опроса, а что-то, что нужно учитывать в реальном мире.

1

Если IO не является ограничением (из-за бесконечной емкости ввода-вывода), вы можете сосредоточиться на количестве доступных вам ядер.

ExecutorService threadPool = Executors.newFixedThreadPool(
          Runtime.getRuntime().availableProcessors()); 

Производительность будет дополнительно улучшена, если вы используете newWorkStealingPool в исполнителях (от Java 8 выпуска)

public static ExecutorService newWorkStealingPool() 

Создает рабочую крадущую пул потоков, используя все доступные процессоры, как его целевой уровень параллелизма ,

Смежные вопросы