предисловие
Механизм планирования потоков Java реализуется JVM.Если есть несколько потоков, и вы хотите, чтобы некоторые потоки имели более длительное время выполнения или некоторые потоки выделяли меньше времени выполнения, тогда задействован «приоритет потока».
приоритет
Java делит приоритет потока на 10 уровней.При создании потока, если он явно не объявлен, используется приоритет по умолчанию.JVM будет распределять вероятность времени выполнения в соответствии с приоритетом каждого потока. Есть три константыThread.MIN_PRIORITY
,Thread.NORM_PRIORITY
,Thread.MAX_PRIORITY
Соответственно представляют минимальное значение приоритета (1), значение приоритета по умолчанию (5) и максимальное значение приоритета (10).
Поскольку реализация JVM основана на операционной системе хоста, должно быть какое-то отношение отображения между значением приоритета Java и собственными приоритетами потоков различных операционных систем, которого достаточно, чтобы инкапсулировать приоритеты всех операционных систем, чтобы обеспечить унифицированная приоритетная семантика. Например, значение приоритета от 1 до 10 может быть сопоставлено со значением приоритета от -20 до 19 в Linux, в то время как в системе Windows будет 9 приоритетов для сопоставления.
Высокий приоритет для выполнения в первую очередь?
Можем ли мы использовать размер значения приоритета для управления порядком выполнения потоков? Очевидно, что нет. Это связано с тем, что существует множество факторов, влияющих на приоритет потока, в том числе:
- Различные версии операционной системы и JVM могут вести себя по-разному.
- Приоритет может иметь разные значения для разных планировщиков операционных систем.
- Некоторые планировщики операционных систем не поддерживают приоритет.
- Для операционной системы приоритет потоков делится на «глобальный» и «локальный», и вообще приоритеты разных процессов не зависят друг от друга.
- Как упоминалось ранее, разные операционные системы имеют разные определения приоритета, а Java определяет только от 1 до 10.
- Операционная система часто увеличивает приоритет потоков, которые не выполняются в течение длительного времени.
- Планировщик потоков операционной системы может иметь определенную временную стратегию настройки приоритета при возникновении потоков и так далее.
один пример
Вот простой пример, результаты каждого запуска двух потоков могут не совпадать.
public class ThreadPriorityTest {
public static void main(String[] args) {
Thread t = new MyThread();
t.setPriority(10);
t.setName("00");
Thread t2 = new MyThread();
t2.setPriority(8);
t2.setName("11");
t2.start();
t.start();
}
static class MyThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++)
System.out.println(this.getName());
}
}
}
11
00
00
00
00
00
11
11
11
11
метод setPriority
Этот метод используется для установки приоритета, логика такова:
- Проверьте, есть ли у вас разрешение на доступ к потоку.
- Проверьте действительность значения приоритета, должно быть в
MIN_PRIORITY
а такжеMAX_PRIORITY
между. - Нельзя превышать максимальное значение приоритета группы потоков.
- перечислить
setPriority0
Родной метод.
public static final int MIN_PRIORITY = 1;
public static final int NORM_PRIORITY = 5;
public static final int MAX_PRIORITY = 10;
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
private native void setPriority0(int newPriority);
локальная реализация
Собственные методы, объявленные на уровне Java, соответственно реализованы в Thread.c,setPriority0
это метод, зарегистрированный в JVM, который совпадает с методом в JVMJVM_SetThreadPriority
Функция связана, поэтому логика реализации находится вJVM_SetThreadPriority
в функции. Логика такова:
-
JVMWrapper("JVM_SetThreadPriority")
для отладки. - Получите мьютекс через MutexLocker.
- Преобразуется в объект oop, используемый уровнем JVM, который является описанием объекта Thread уровня Java в JVM.
- Установите значение атрибута приоритета объекта oop, здесь
java_lang_Thread::set_priority
установить, т.е.java_thread->int_field_put(_priority_offset, priority)
, здесь путем вычисления адреса смещения, хранящегося в свойстве приоритета в объекте oop, а затем присваивании значения этому адресу. - пройти через
java_lang_Thread::thread
Получите указатель JavaThread, т.е.(JavaThread*)java_thread->address_field(_eetop_offset)
, который получается путем вычисления смещения eetop, которое является атрибутом в классе Thread уровня Java. Причина, по которой это можно сделать, заключается в том, что объект JavaThread поддерживает указатель на oop, который также поддерживает указатель на объект JavaThread. - последний звонок
Thread::set_priority
Чтобы установить приоритет потока на уровне операционной системы, вызовитеos::set_priority
реализовать.
static JNINativeMethod methods[] = {
...
{"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority},
...
};
JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
JVMWrapper("JVM_SetThreadPriority");
MutexLocker ml(Threads_lock);
oop java_thread = JNIHandles::resolve_non_null(jthread);
java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
JavaThread* thr = java_lang_Thread::thread(java_thread);
if (thr != NULL) {
Thread::set_priority(thr, (ThreadPriority)prio);
}
JVM_END
void Thread::set_priority(Thread* thread, ThreadPriority priority) {
debug_only(check_for_dangling_thread_pointer(thread);)
(void)os::set_priority(thread, priority);
}
см. далееos::set_priority
Реализация функции:
- Во-первых, определите достоверность значения приоритета.
- с последующим
java_to_os_priority
Сопоставьте приоритет уровня Java с приоритетом операционной системы.Разные операционные системы различаются и подробно описаны в разделе «Сопоставление приоритетов» ниже. - наконец позвоню
set_native_priority
Функция устанавливает приоритет потока, который различен для разных операционных систем, подробно описан в разделе "Настройка приоритета потока ОС" ниже.
OSReturn os::set_priority(Thread* thread, ThreadPriority p) {
if (p >= MinPriority && p <= MaxPriority) {
int priority = java_to_os_priority[p];
return set_native_priority(thread, priority);
} else {
assert(false, "Should not happen");
return OS_ERR;
}
}
сопоставление приоритетов
Значение приоритета слоя Java необходимо преобразовать в значение приоритета операционной системы.В середине есть операция сопоставления.Давайте посмотрим, как его сопоставить? упоминалось ранее черезjava_to_os_priority
Convert, это массив, всего в этом массиве 12 элементов. Посмотрим на значения для операционных систем Linux и Windows:
Для Linux
1 и 10 уровня Java соответствуют уровням 4 и -5 Linux соответственно. Диапазон значений приоритета потоков Linux составляет от -20 до 19, из которых -20 — самый высокий приоритет, а 19 — самый низкий приоритет. 4, чтобы сопоставить приоритеты от 1 до 10.
int os::java_to_os_priority[CriticalPriority + 1] = {
19, // 0 Entry should never be used
4, // 1 MinPriority
3, // 2
2, // 3
1, // 4
0, // 5 NormPriority
-1, // 6
-2, // 7
-3, // 8
-4, // 9 NearMaxPriority
-5, // 10 MaxPriority
-5 // 11 CriticalPriority
};
Для Windows
И 1, и 2 слоя Java отображаются наTHREAD_PRIORITY_LOWEST
, и другие аналогичны, два последовательных значения сопоставляются с одним и тем же значением соответственно.
int os::java_to_os_priority[CriticalPriority + 1] = {
THREAD_PRIORITY_IDLE, // 0 Entry should never be used
THREAD_PRIORITY_LOWEST, // 1 MinPriority
THREAD_PRIORITY_LOWEST, // 2
THREAD_PRIORITY_BELOW_NORMAL, // 3
THREAD_PRIORITY_BELOW_NORMAL, // 4
THREAD_PRIORITY_NORMAL, // 5 NormPriority
THREAD_PRIORITY_NORMAL, // 6
THREAD_PRIORITY_ABOVE_NORMAL, // 7
THREAD_PRIORITY_ABOVE_NORMAL, // 8
THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority
THREAD_PRIORITY_HIGHEST, // 10 MaxPriority
THREAD_PRIORITY_HIGHEST // 11 CriticalPriority
};
Платформа Windows имеет следующие значения, вы можете видеть, что не все значения сопоставлены.
THREAD_MODE_BACKGROUND_BEGIN
THREAD_MODE_BACKGROUND_END
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_IDLE
THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_TIME_CRITICAL
Настройка приоритета потока ОС
Как упоминалось ранее, JVM вызываетset_native_priority
Функция устанавливает приоритет потока операционной системы.Эта функция будет выполнять различную обработку в зависимости от разных операционных систем.Давайте посмотрим на ситуацию с Linux и Windows.
Для Linux
функция системы вызоваsetpriority
для достижения и успешно возвращает OS_OK.
OSReturn os::set_native_priority(Thread* thread, int newpri) {
if (!UseThreadPriorities || ThreadPriorityPolicy == 0) return OS_OK;
int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri);
return (ret == 0) ? OS_OK : OS_ERR;
}
Для Windows
функция системы вызоваSetThreadPriority
для достижения и успешно возвращает OS_OK.
OSReturn os::set_native_priority(Thread* thread, int priority) {
if (!UseThreadPriorities) return OS_OK;
bool ret = SetThreadPriority(thread->osthread()->thread_handle(), priority) != 0;
return ret ? OS_OK : OS_ERR;
}
------------- Рекомендуем прочитать ------------
Резюме моей статьи за 2017 год — машинное обучение
Краткое изложение моих статей за 2017 год — Java и промежуточное ПО
Резюме моих статей 2017 года — глубокое обучение
Краткое изложение моих статей за 2017 год — исходный код JDK
Резюме моей статьи за 2017 год — обработка естественного языка
Резюме моих статей 2017 года — Java Concurrency
Поговори со мной, задай мне вопросы:
Меню официальной учетной записи было разделено на «Сводка для чтения», «Распределенное», «Машинное обучение», «Глубокое обучение», «НЛП», «Глубина Java», «Ядро параллелизма Java», «Исходный код JDK», "Tomcat Core" "Подождите, может быть, есть тот, который соответствует вашему аппетиту.
Зачем писать «Анализ проектирования ядра Tomcat»
Добро пожаловать, чтобы следовать: