В этой статье мы подробно обсудим приоритеты потоков и различные типы приоритетов потоков в Java, а также то, как планировщик потоков выполняет различные потоки на основе их приоритетов. Мы также увидим, как можно задать приоритет потока и как можно получить приоритет существующего потока.
1. Введение в приоритет потока
Каждый поток в Java имеет приоритет. Это может быть приоритет по умолчанию, назначенный JVM, или настраиваемый приоритет, явно предоставленный программистом. Допустимый диапазон приоритета потока — от 1 до 10, где 1 — минимальный, а 10 — максимальный приоритет. Приоритет по умолчанию — 5.
В многопоточной среде планировщик потоков использует приоритеты при распределении процессоров между потоками для их выполнения.
- Поток с наивысшим приоритетом будет выполнен первым, за ним последуют другие потоки с низким приоритетом, ожидающие своего выполнения. Это означает, что планировщик отдает предпочтение потокам с высоким приоритетом.
- Если несколько потоков имеют одинаковый приоритет, то порядок выполнения потоков будет определяться планировщиком потоков на основе некоторого внутреннего алгоритма: циклического, вытесняющего планирования или алгоритма FCFS(первым пришел, первым обслужен).
- Планировщик потоков является частью JVM и различается от JVM к JVM, поэтому мы не можем ожидать точного алгоритма, используемого планировщиком.

См. также: Жизненный цикл потока
2. Типы приоритета потоков
Класс Thread содержит 3 константы для определения приоритетов потоков:
- MIN_PRIORITY: Это минимальный приоритет со значением 1.
- NORM_PRIORITY: Это обычный приоритет по умолчанию со значением 5.
- MAX_PRIORITY: Это максимальный приоритет со значением 10.
public static int MIN_PRIORITYpublic static int NORM_PRIORITYpublic static int MAX_PRIORITY
3. Работа с приоритетом потока
Давайте теперь рассмотрим, как мы можем использовать приоритет потока в нашем коде и как мы можем изменить приоритет потока в соответствии с требованиями.
3.1 Получение и установка приоритета потока
Для получения и установки приоритета потока можно использовать следующие методы:
- int getPriority(): возвращает приоритет указанного потока.
- void setPriority(int newPriority): устанавливает новый приоритет для потока. Допустимый диапазон для передачи нового значения приоритета в качестве аргумента этому методу — от 1 до 10. Если мы передадим значение за пределами этого диапазона, этот метод выдаст исключение 'IllegalArgumentException'.
3.2 Пример приоритета потока
Давайте теперь рассмотрим пример, объясняющий использование приоритетов потоков. В этом примере мы создаем новый поток, расширяя класс Thread, а затем выполняем операции get и set для приоритетов потоков.
// Creating 3 ThreadsThread thread1 = new Thread();Thread thread2 = new Thread();Thread thread3 = new Thread();// Getting Priorities of above threadsSystem.out.println("Thread1 priority : " + thread1.getPriority()); // Print ‘5’ as default prioritySystem.out.println("Thread2 priority : " + thread2.getPriority()); // Print ‘5’ as default prioritySystem.out.println("Thread3 priority : " + thread3.getPriority()); // Print ‘5’ as default priority// Setting priority for above threadsthread1.setPriority(4);// Setting Priority of 1 using Thread constant for minimum prioritythread2.setPriority(Thread.MIN_PRIORITY);// thread3.setPriority(15); // This will throw IllegalArgumentException// Again getting Priorities for above ThreadsSystem.out.println("Thread1 new priority : " + thread1.getPriority()); // Print ‘4’ as new prioritySystem.out.println("Thread2 new priority : " + thread2.getPriority()); // Print ‘1’ as new priority
3.3 Приоритет потока основного потока
Основной поток имеет приоритет по умолчанию '5'. Мы можем изменить приоритет основного потока с помощью класса setPriority().
class MainThreadDemo extends Thread{public static void main(String[] args){// Getting priority for main threadSystem.out.println(Thread.currentThread().getPriority());// Print ‘5’ as default priority// Setting priority for main threadThread.currentThread().setPriority(Thread.MAX_PRIORITY);// Getting priority for main thread againSystem.out.println(Thread.currentThread().getPriority()); // Print ‘10’ as new priority}}
4. Приоритет потока относительно родительско-дочерних отношений
Если мы не предоставляем приоритет потоку, то основной поток будет иметь приоритет по умолчанию 5. А для всех остальных потоков приоритет по умолчанию наследуется от родительского потока к дочернему потоку.
Это означает, что какой бы приоритет ни имел родительский поток, такой же приоритет наследуется и для дочернего потока.
class ThreadDemo extends Thread{public void run(){System.out.println(“Inside run method”);}public static void main(String[] args){// Setting priority for main threadThread.currentThread().setPriority(7);// Printing main thread prioritySystem.out.println("Main thread priority: " + Thread.currentThread().getPriority());// Creating child threadThreadDemo childThread = new ThreadDemo();// Printing child thread prioritySystem.out.println("Child thread priority: " + childThread.getPriority()); //7}}
Обратите внимание на вывод программы. Мы видим, что и родительский поток(main), и дочерний поток(childThread) имеют одинаковые приоритеты. Несмотря на то, что мы не установили приоритет дочернего потока, он выбирает тот же приоритет, что и его родительский поток(в данном случае основной поток).
5. Выполнение потоков с одинаковым приоритетом
Мы знаем, что планировщик потоков обычно сначала выполняет потоки с высоким приоритетом, а затем потоки с низким приоритетом. У нас может быть сценарий, в котором 2 потока имеют одинаковый приоритет, поэтому в этом случае мы не можем угадать, какой поток выполнится первым. Это полностью зависит от внутреннего алгоритма, используемого планировщиком потоков для планирования таких потоков.
Давайте рассмотрим пример и для этого сценария.
public class ThreadPriorityDemo {public static void main(String[] args) {// Creating child tasksChildTask childTask1 = new ChildTask();ChildTask childTask2 = new ChildTask();// Start Child Threadsnew Thread(childTask1).start();new Thread(childTask2).start();System.out.println(Thread.currentThread().getName() + " executed by main thread");}}class ChildTask implements Runnable {public void run(){System.out.println(Thread.currentThread().getName() + " executed by child thread");}}
В этом примере родительский поток(главный поток) и дочерний поток(поток1) имеют одинаковый приоритет '5'. Обратите внимание на вывод программы ниже. Мы можем видеть 2 возможных вывода для этого сценария, поскольку планировщик различается от системы к системе и может сначала выполнить любой поток(главный или дочерний), поскольку оба имеют одинаковый приоритет.
main executed by main threadThread-1 executed by child threadThread-0 executed by child thread
6. Заключение
Мы рассмотрели приоритеты потоков и их типы в Java, а также то, как можно получить и установить приоритет потока для различных потоков с практическими примерами.
Мы также рассмотрели сценарии, в которых несколько потоков имеют одинаковый приоритет, и то, как приоритет потоков ведет себя в зависимости от отношений родительских и дочерних потоков.