Java thread priority

In the Thread class, the following attributes are used to represent priorities.

private int priority;
Copy the code

We can set the newPriority by setPriority(int newPriority) and get the priority of the thread by getPriority().

Some sources point to the following example: Java threads have a default priority of 5.

public static void main(String[] args) { Thread thread = new Thread(); System.out.println(thread.getPriority()); } // Print the result: 5Copy the code

If we change the priority of the current thread to 4, we find that the priority of the child thread is also 4.

public static void main(String[] args) { Thread.currentThread().setPriority(4); Thread thread = new Thread(); System.out.println(thread.getPriority()); } // Print the result: 4Copy the code

The default priority for a thread is 5. For a new thread, it should be 5, but it should be 4. Let’s look at the source code for Thread initializing Priority.

Thread parent = currentThread();
this.priority = parent.getPriority();
Copy the code

The default priority of a thread is to inherit the parent thread’s priority. In the example above, we set the parent thread’s priority to 4, causing the child thread’s priority to become 4 as well.

To be more precise, the default priority of the child thread is the same as that of the parent thread, and the default priority of the Main Java thread is 5.

Java defines three priorities, namely lowest priority (1), normal priority (5), and highest priority (10). The code is shown below. The Java priority range is [1, 10]. Setting the priority of any other number will throw IllegalArgumentException.

/**
 * The minimum priority that a thread can have.
 */
public final static int MIN_PRIORITY = 1;

/**
 * The default priority that is assigned to a thread.
 */
public final static int NORM_PRIORITY = 5;

/**
 * The maximum priority that a thread can have.
 */
public final static int MAX_PRIORITY = 10;
Copy the code

Next, the role of thread priority. Let’s look at the following code. The code logic creates 3000 threads: 1000 priority 1 threads, 1000 priority 5 threads, and 1000 priority 10 threads. MinTimes is used to record the sum of 1000 MIN_PRIORITY thread runtime timestamps, normTimes is used to record 1000 NORM_PRIORITY thread runtime timestamps, MaxTimes is used to record the sum of 1000 MAX_PRIORITY thread runtime timestamps. By counting the sum of time stamps for each priority run, a smaller value indicates a higher priority. Let’s run it.

public class TestPriority { static AtomicLong minTimes = new AtomicLong(0); static AtomicLong normTimes = new AtomicLong(0); static AtomicLong maxTimes = new AtomicLong(0); public static void main(String[] args) { List<MyThread> minThreadList = new ArrayList<>(); List<MyThread> normThreadList = new ArrayList<>(); List<MyThread> maxThreadList = new ArrayList<>(); int count = 1000; for (int i = 0; i < count; i++) { MyThread myThread = new MyThread("min----" + i); myThread.setPriority(Thread.MIN_PRIORITY); minThreadList.add(myThread); } for (int i = 0; i < count; i++) { MyThread myThread = new MyThread("norm---" + i); myThread.setPriority(Thread.NORM_PRIORITY); normThreadList.add(myThread); } for (int i = 0; i < count; i++) { MyThread myThread = new MyThread("max----" + i); myThread.setPriority(Thread.MAX_PRIORITY); maxThreadList.add(myThread); } for (int i = 0; i < count; i++) { maxThreadList.get(i).start(); normThreadList.get(i).start(); minThreadList.get(i).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } system.out.println ("maxPriority: "+ maxtimes.get ()); System.out.println("normPriority: "+ normtimes.get ()); System.out.println("minPriority: "+ mintimes.get ()); System.out.println(" Normtimes.get () -maxtimes.get ()) + "ms"); system.out.println (" Normtimes.get () -maxtimes.get ()) + "ms"); System.out.println(" Mintimes.get () -normtimes.get ()) + "ms"); system.out.println (" Mintimes.get () -normtimes.get ()) + "ms"); } static class MyThread extends Thread { public MyThread(String name) { super(name); } @Override public void run() { System.out.println(this.getName() + " priority: " + this.getPriority()); switch (this.getPriority()) { case Thread.MAX_PRIORITY : maxTimes.getAndAdd(System.currentTimeMillis()); break; case Thread.NORM_PRIORITY : normTimes.getAndAdd(System.currentTimeMillis()); break; case Thread.MIN_PRIORITY : minTimes.getAndAdd(System.currentTimeMillis()); break; default: break; }}}}Copy the code

The result is as follows:

# first part Max ----0 priority: 10 norm-- 0 priority: 5 Max ----1 priority: 10 Max ----2 priority: 10 norm-- 2 priority: 10 norm-- 2 priority: 10 5 min----4 priority: 1 ....... max----899 priority: 10 min----912 priority: 1 min----847 priority: 5 min----883 priority: MaxPriority statistics: 1568986695523243 normPriority statistics: 1568986695526080 minPriority statistics: 1568986695545414 difference between the common priority and the highest priority: 2837ms difference between the lowest priority and the common priority: 19334msCopy the code

Let’s analyze the results. A thread with a higher priority does not necessarily have a higher priority than a thread with a lower priority. Or to put it another way: code execution order is independent of thread priority. Looking at the results of the second part, we can see that the sum of the execution timestamps of the 1000 threads with the highest priority is the smallest, and the sum of the execution timestamps of the 1000 threads with the lowest priority is the largest, so we can know: A batch of high-priority threads will execute before a batch of low-priority threads, that is, high-priority threads are more likely to obtain CPU resources before low-priority threads.

Are there really 10 thread levels in each operating system?

Java, as a cross-platform language, has 10 levels of threads, but the priority values of threads mapped to different operating systems are different. The following tutorial will show you how to look up thread priority mapping values in the OpenJDK source code.

Looking at the Thread source code, setting the Thread priority eventually calls the local method setPriority0();

private native void setPriority0(int newPriority);
Copy the code

SetPriority0 () = JVM_SetThreadPriority;

static JNINativeMethod methods[] = {
    ...
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    ...
};
Copy the code

We find the corresponding snippet in JVM_SetThreadPriority;

JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) JVMWrapper("JVM_SetThreadPriority"); // Ensure that the C++ Thread and OSThread structures aren't freed before we operate 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 not yet started; priority pushed down when it is Thread::set_priority(thr, (ThreadPriority)prio); } JVM_ENDCopy the code

The key is java_lang_Thread::set_Priority(). Continue looking for set_Priority() in thread.cpp.

void Thread::set_priority(Thread* thread, ThreadPriority priority) {
  trace("set priority", thread);
  debug_only(check_for_dangling_thread_pointer(thread);)
  // Can return an error!
  (void)os::set_priority(thread, priority);
}
Copy the code

Finding that the above code finally calls OS ::set_priority(), continue to find the set_priority() method of os.cpp;

OSReturn os::set_priority(Thread* thread, ThreadPriority p) { #ifdef ASSERT if (! (! thread->is_Java_thread() || Thread::current() == thread || Threads_lock->owned_by_self() || thread->is_Compiler_thread()  )) { assert(false, "possibility of dangling Thread pointer"); } #endif 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; }}Copy the code

Finally, we found the priority code javA_TO_OS_PRIORITY [p] that was eventually converted to each operating system. The next step was to find the value of this array for each operating system. For example, here are the priority values for Linux.

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
};
Copy the code

Well, you should know how to find the Java thread priority [1,10] that corresponds to the priority value in each operating system. Let me give you some statistics.

Java thread priority

Linux

Windows

Apple

Bsd

Solaris

1

4

2 –

27

0

0

2

3

2 –

28

3

32

3

2

– 1

29

6

64

4

1

– 1

30

10

96

5

0

0

31

15

127

6

– 1

0

32

18

127

7

2 –

1

33

21

127

8

– 3

1

34

25

127

9

4 –

2

35

28

127

10

– 5

2

36

31

127

Windows only finds the following constants in the OpenJDK source code.

THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_HIGHEST
Copy the code

The corresponding values are found in the function interface documentation provided by Microsoft, linked here: docs.microsoft.com/en-us/windo…

We can also see some problems in this table. Even if we set a higher priority in Java code, the threads mapped to the operating system are not necessarily higher than those with a lower priority. They are probably the same priority. Looking at the extreme example of the Solaris operating system, priorities 5 to 10 map to the same thread level.

Think back to the example above why 3000 threads with MAX_PRIORITY 1000 threads will execute first? This works because our three priorities map to three different levels of Windows operating system threads. Let’s say I change 1, 5, 10 to 5, 6, 7, and the result is different.

Finally, remember: don’t treat thread priority like a silver bullet. A thread with a higher priority doesn’t have to execute before a thread with a lower priority.

This thread priority article also ended paragraph, friends after reading feel useful trouble to help a point in the look, recommend to friends around to see