Gymterview
middle

Что такое планировщик процессов (scheduler)?

Планировщик процессов (scheduler) — это компонент ядра ОС, который определяет, какой процесс или поток будет выполняться на каком ядре процессора в каждый момент времени, обеспечивая многозадачность.

Аналогия: планировщик — это диспетчер в аэропорту, который решает, какой самолёт (процесс) получит взлётную полосу (ядро CPU) и на сколько времени. Если самолётов больше, чем полос, они ждут в очереди и взлетают по очереди.

Зачем нужен планировщик

В типичной системе количество запущенных потоков значительно превышает количество ядер CPU. Например, на 8-ядерном процессоре может быть запущено 200+ потоков. Планировщик создаёт иллюзию одновременного выполнения, быстро переключая контекст между потоками.

Основные понятия

  • Квант времени (time slice / quantum) — максимальное время непрерывного выполнения процесса на CPU перед принудительным переключением. Обычно 1-10 мс.
  • Приоритет — числовое значение, определяющее важность процесса. Процессы с более высоким приоритетом получают больше процессорного времени.
  • Вытесняющая многозадачность (preemptive multitasking) — ОС может принудительно забрать CPU у процесса по истечении кванта или при появлении более приоритетного процесса. Используется во всех современных ОС.

Алгоритмы планирования

Алгоритм Описание Достоинства / Недостатки
Round Robin (RR) Каждый процесс получает равный квант времени по очереди Простой и справедливый, но не учитывает приоритеты
Priority Scheduling Процесс с наивысшим приоритетом выполняется первым Учитывает важность, но возможно голодание (starvation) низкоприоритетных процессов
CFS (Completely Fair Scheduler) Используется в Linux. Выбирает процесс с минимальным «виртуальным временем выполнения». Реализован на красно-чёрном дереве Справедливый, эффективный, масштабируемый
Multilevel Feedback Queue Несколько очередей с разными приоритетами. Процессы перемещаются между очередями в зависимости от поведения Адаптивный, но сложен в настройке

Типы процессов по характеру нагрузки

  • CPU-bound — интенсивно используют процессор (вычисления, сжатие, рендеринг). Получают более длинные кванты, чтобы не тратить время на частое переключение контекста.
  • I/O-bound — часто ожидают ввода/вывода (сетевые запросы, чтение с диска). Получают более высокий приоритет, так как быстро освобождают CPU и не занимают его подолгу.

Значение для Java-разработчика

  • Thread.setPriority(int) — подсказка планировщику ОС, но не гарантия. На практике разница между приоритетами потоков Java часто незаметна.
  • Количество потоков в пуле (ExecutorService) следует выбирать с учётом характера задач:
    • Для CPU-bound: ~количество ядер (Runtime.getRuntime().availableProcessors()).
    • Для I/O-bound: значительно больше (десятки-сотни), так как потоки большую часть времени ожидают I/O.
  • Виртуальные потоки (Java 21+) имеют собственный планировщик внутри JVM (ForkJoinPool), но carrier threads по-прежнему планируются ОС.
  • Чрезмерное количество потоков ОС (тысячи) приводит к деградации из-за частого переключения контекста. Именно эту проблему решают виртуальные потоки.

Вывод

Планировщик ОС распределяет процессорное время между потоками, используя алгоритмы на основе приоритетов и квантов времени. Для Java-разработчика ключевой практический вывод: размер пула потоков зависит от типа задачи — CPU-bound или I/O-bound. Виртуальные потоки Java 21 снимают ограничение на количество одновременных потоков для I/O-bound задач.

На собеседовании: middle-вопрос, часто задаётся в контексте настройки пулов потоков. Покажите, что понимаете разницу между CPU-bound и I/O-bound, и объясните, почему для CPU-bound задач оптимальный размер пула ~ числу ядер. Упоминание CFS и его реализации на красно-чёрном дереве покажет глубокое понимание.