Какие методы приоритизации потоков существуют
Что проверяют
Знаете ли вы, что приоритет потока в Java это лишь подсказка планировщику, и умеете ли приоритизировать работу другими средствами. Следом обычно спрашивают, как сделать, чтобы срочные задачи в пуле выполнялись раньше фоновых.
Как отвечать
Сначала то, что даёт сам Thread:
setPriority(int): значения отThread.MIN_PRIORITY(1) доThread.MAX_PRIORITY(10), новый поток наследует приоритет создателя, уmainэтоNORM_PRIORITY(5). Верхний предел ограничиваетThreadGroup. Как это ложится на ОС, решает JVM: на Linux HotSpot по умолчанию приоритеты фактически не применяет;- виртуальные потоки (Java 21): приоритет всегда
NORM_PRIORITY, вызовsetPriorityигнорируется; Thread.yield(): просьба уступить процессор, которую планировщик вправе проигнорировать. Строить на ней логику нельзя.
Настоящая приоритизация делается на уровне задач:
- очередь с приоритетом:
ThreadPoolExecutorсPriorityBlockingQueueи задачами, реализующимиComparable. Два подвоха:submit()оборачивает задачу вFutureTask, который не сравним, поэтому нуженexecute()или переопределённыйnewTaskFor; очередь неограниченна, и пул никогда не вырастет вышеcorePoolSize; - раздельные пулы: отдельный executor под срочные и под фоновые задачи, чтобы фоновые не заняли все потоки. Это надёжнее любых приоритетов;
- ограничение тяжёлой работы:
Semaphoreили rate limiter на фоновые операции.
Где спотыкаются
Утверждают, что поток с приоритетом 10 выполнится раньше. Спецификация этого не гарантирует, а на типичном Linux-сервере разницы может не быть вовсе.
Предлагают sleep() и yield() как способ «управлять приоритетами». Это снижает пропускную способность и ничего не гарантирует.
Путают проблемы и говорят, что приоритеты вызывают deadlock. Реальные риски другие: голодание низкоприоритетных потоков и инверсия приоритетов, когда важный поток ждёт блокировку, которую держит фоновый. Кстати, честная блокировка new ReentrantLock(true) раздаёт доступ по порядку ожидания, а не по приоритету.