Objective
Java's thread scheduling mechanism is implemented by the JVM, which involves "thread priority" if there are several threads that you want to have a longer execution time for some threads, or if some threads allocate less execution time.
Priority level
Java divides the thread priority into 10 levels, and if a thread is created with a default priority if it is not explicitly declared, the JVM assigns the probability of execution time based on the priority of each thread. There are three constants thread.min_priority, Thread.norm_priority, and thread.max_priority, respectively, representing the minimum priority value (1), the default priority value (5), and the maximum priority value (10).
Because the implementation of the JVM is based on the host operating system, there must be some mapping between the Java priority values and the native thread precedence of the various operating systems, which is sufficient to encapsulate the precedence of all operating systems to provide uniform priority semantics. For example, the 1-10 priority value in Linux may be mapped with a 20-19 priority value, while the Windows system has 9 priorities to map.
Priority high first execution?
Can we control the order of thread execution with the size of the priority value? The answer is clearly not possible. This is because there are a number of factors that affect thread precedence, including:
Different versions of the operating system and JVM may behave differently.
The priority may not be the same for different operating system schedulers.
Some operating system schedulers do not support the priority level.
For the operating system, the priority of the thread is "global" and "local", and the priority of the different processes is independent of each other.
As mentioned earlier, the values defined for different operating system priorities are not the same, whereas Java defines only 1-10.
The operating system often gives a higher priority to threads that are not running for long periods of time.
The thread scheduler for the operating system may have a certain temporal priority adjustment policy when threads occur, and so on.
An example
In the following simple example, two threads may have different results each time they run.
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()); }}
}
SetPriority method
This method is used to set the precedence, with the following logic:
Check if you have permission to access the thread.
Check the legitimacy of priority values, which must be between min_priority and max_priority.
The maximum priority value of a thread group cannot be exceeded.
Call the SetPriority0 local method.
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);
Local implementation
The native method corresponding to the Java layer declaration is implemented in THREAD.C, SetPriority0 is a method registered in the JVM that binds to the jvm_setthreadpriority function in the JVM, so the implementation logic is JVM_SETTHREADPRI In the Ority function. The logic is:
Jvmwrapper ("Jvm_setthreadpriority") is used for debugging.
Gets the mutex through Mutexlocker.
Into the OOP object used by the JVM layer, which is the description of the Java layer Thread object in the JVM.
Sets the value of the priority attribute of the Oop object, which is set by java_lang_thread::set_priority, i.e. java_thread->int_field_put (_priority_offset, precedence) , where the offset address stored by the priority attribute in the OOP object is computed, and then the value is set to that address.
Gets the Javathread pointer through Java_lang_thread::thread, which is (javathread*) Java_thread->address_field (_eetop_offset), which computes Eetop offset to get, Eetop belongs to the Java layer attribute in the Thread class. The reason you can do this is because the Javathread object maintains a pointer to OOP, and OOP also maintains a pointer to the Javathread object.
Finally call Thread::set_priority to set the operating system-level thread priority, which is achieved by calling 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);
}
Then look at the implementation of the Os::set_priority function:
First, the legitimacy of the priority value is judged.
The second is to map the Java layer's priority to the priority of the operating system through java_to_os_priority, with different operating systems, in the following "priority mapping".
Finally, call the Set_native_priority function to set the thread priority, various operating systems are not the same, in the following "OS Thread priority settings" in detail.
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;
}
}
Priority mapping
The priority value of the Java layer needs to be transferred to the priority value of the operating system, there is a mapping operation in the middle, how to map? In front of the java_to_os_priority conversion, it is an array of 12 elements. Here's a look at the values for Linux and Windows operating systems:
For Linux
The Java layer's 1,10 of 4 and -5,linux threads for Linux respectively have a priority value range of 20 to 19, where 20-bit highest priority, 19-bit lowest priority, and Java uses 5 to 4来 mappings of 1 to 10 of priority.
int os::java_to_os_priority[criticalpriority + 1] = {
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,//Maxpriority
-5//Criticalpriority
};
For Windows
Both 1 and 2 of the Java layer are mapped to thread_priority_lowest, and others are similar, with two successive values mapped to the same value.
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,//Maxpriority
Thread_priority_highest//Criticalpriority
};
The Windows platform has the following values, and you can see that all values are not mapped.
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
OS Thread Priority setting
As mentioned earlier, the JVM sets the thread priority of the operating system by calling the Set_native_priority function, which is handled differently depending on the operating system, looking at the Linux and Windows scenarios.
For Linux
Call system function setpriority to implement, successfully return 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;
}
For Windows
Call system function SetThreadPriority to implement, successfully return 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;
}
Priority from Java to JVM to OS threads