Java thread value nump prio does not match real thread priority in linux?

I intend to use thread priorities in my Java code. The application should work on my Linux system:

>uname -a Linux <host> 3.0.0-15-generic #26-Ubuntu SMP <date> x86_64 x86_64 x86_64 GNU/Linux >java -version java version "1.6.0_23" OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.1) OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode) 

After some reading on the Internet, I run my test application with the following command:

 sudo java -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=1 -jar ThreadPriorityTest.jar 

The test application consists of the following two classes:

 package ch.mypackage; public class CountingRunnable implements Runnable{ private long count=0; private boolean goOn=true; public long getCount() { return count; } public void stop(){ goOn=false; } public void run() { for(long iteration=0;goOn&&iteration<Long.MAX_VALUE;++iteration){ ++count; } } } package ch.mypackage; public class PriorizedCountingThreads { private static final int NUM_MILLIS_TO_COUNT_FOR = 1*60*1000; private static CountingRunnable[] runnables; private static Thread[] threads; /** * @param args */ public static void main(String[] args) { Thread.currentThread().setPriority(Thread.MAX_PRIORITY); System.out.println("MIN_PRIORITY: "+Thread.MIN_PRIORITY); System.out.println("MAX_PRIORITY: "+Thread.MAX_PRIORITY); int numPriorityLevels=(Thread.MAX_PRIORITY-Thread.MIN_PRIORITY)+1; init(numPriorityLevels); startThreads(); try { Thread.sleep(NUM_MILLIS_TO_COUNT_FOR); } catch (InterruptedException e) { e.printStackTrace(); } stopRunnables(); printCounts(); } private static void printCounts() { for(int i=0;i<runnables.length;++i){ System.out.println(threads[i].getName()+" has priority: "+threads[i].getPriority()+" and count:"+runnables[i].getCount()); } } private static void stopRunnables() { for(int i=0;i<runnables.length;++i){ runnables[i].stop(); } } private static void startThreads() { for(int i=0;i<threads.length;++i){ threads[i].start(); } } private static void init(int numPriorityLevels) { runnables=new CountingRunnable[numPriorityLevels]; threads=new Thread[runnables.length]; for(int i=0;i<runnables.length;++i){ int priority=i+1; runnables[i]=new CountingRunnable(); threads[i]=new Thread(runnables[i]); threads[i].setPriority(priority); threads[i].setName("PriorityThread_"+priority); } } } 

If I run the program within one minute (NUM_MILLIS_TO_COUNT_FOR = 1 * 60 * 1000), I get the following output:

 MIN_PRIORITY: 1 MAX_PRIORITY: 10 PriorityThread_1 has priority: 1 and count:12658044343 PriorityThread_2 has priority: 2 and count:19008431582 PriorityThread_3 has priority: 3 and count:30618946099 PriorityThread_4 has priority: 4 and count:34408365142 PriorityThread_5 has priority: 5 and count:36694025023 PriorityThread_6 has priority: 6 and count:40493710165 PriorityThread_7 has priority: 7 and count:42826305342 PriorityThread_8 has priority: 8 and count:42203891414 PriorityThread_9 has priority: 9 and count:43128747383 PriorityThread_10 has priority: 10 and count:43416371500 

According to this result, priorities seem to have the expected impact! But if I dump the stream with "jstack" or "kill -s QUIT", then I get the following output, which implies that EVERY THREAD HAS A VERY PRIORITY (prio = 10):

  "PriorityThread_10" prio=10 tid=0x00007ff7e406f800 nid=0x12e6 runnable [0x00007ff7e2562000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_9" prio=10 tid=0x00007ff7e406d800 nid=0x12e5 runnable [0x00007ff7e2663000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_8" prio=10 tid=0x00007ff7e406b000 nid=0x12e4 runnable [0x00007ff7e2764000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_7" prio=10 tid=0x00007ff7e4069000 nid=0x12e3 runnable [0x00007ff7e2865000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_6" prio=10 tid=0x00007ff7e4067000 nid=0x12e2 runnable [0x00007ff7e2966000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_5" prio=10 tid=0x00007ff7e4065000 nid=0x12e1 runnable [0x00007ff7e2a67000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_4" prio=10 tid=0x00007ff7e4063000 nid=0x12e0 runnable [0x00007ff7e2b68000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_3" prio=10 tid=0x00007ff7e4061000 nid=0x12df runnable [0x00007ff7e2c69000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_2" prio=10 tid=0x00007ff7e405d000 nid=0x12de runnable [0x00007ff7e2d6a000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) "PriorityThread_1" prio=10 tid=0x00007ff7e4049800 nid=0x12dd runnable [0x00007ff7e2e6b000] java.lang.Thread.State: RUNNABLE at ch.mypackage.CountingRunnable.run(CountingRunnable.java:17) at java.lang.Thread.run(Thread.java:679) 

If I do the same on a Windows machine, the prio values โ€‹โ€‹are correct, according to the priority mappings I found here .

So, is this a bug in jstack, or am I doing something wrong?

If I execute "top | grep java", I get the following:

 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3394 root 20 0 4444m 15m 8376 S 789 0.1 0:47.52 java 

which implies that the main thread has a priority of 20, while "top -H | grep java" leads to the following output:

  PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3457 root 15 -5 4444m 15m 8384 R 99 0.1 0:08.60 java 3456 root 16 -4 4444m 15m 8384 R 97 0.1 0:08.41 java 3455 root 17 -3 4444m 15m 8384 R 93 0.1 0:08.42 java 3454 root 18 -2 4444m 15m 8384 R 97 0.1 0:08.27 java 3453 root 19 -1 4444m 15m 8384 R 97 0.1 0:07.50 java 3452 root 20 0 4444m 15m 8384 R 51 0.1 0:07.44 java 3451 root 21 1 4444m 15m 8384 R 35 0.1 0:04.83 java 3450 root 22 2 4444m 15m 8384 R 99 0.1 0:04.78 java 3449 root 23 3 4444m 15m 8384 R 95 0.1 0:07.47 java 3448 root 24 4 4444m 15m 8384 R 18 0.1 0:02.85 java 

which shows that java thread priorities really affect OS thread priorities.

But where does jstack have a value of 10 in prio = 10 of? Is this just an arbitrary value?

+8
java multithreading linux pthreads jstack
source share
2 answers

Thread priority in Java is a very sensitive object ... Here you can find an intermediate post on StackOverlow: https://stackoverflow.com/a/2170304/1343096

Basically try changing the priority policy to 42:

 -XX:ThreadPriorityPolicy=42 

Let us know if this is a trick for you!

You can find all the explanations by following the link.

0
source share

Java 7 docs state

NOTE This utility is not supported and may or may not be available in future versions of the JDK.

So, I would suggest that the output of jstack might be inaccurate, since the implementation details in linux can be changed.

The values โ€‹โ€‹indicated by htop -H correspond to this article , which you included in your question, and those on which java-processes are executed inside the linux kernel.

If you need to map jstack output to streams reported by top -H , you only need to convert nid from jstack to decimal or pid from top -H to hex. See article

Regarding your source code: the program will not be named when I run it. Three tips for writing multitasking code:

  • If you know that everything is done (as after calling printCounts() from main ), feel free to use System.exit(0); therby, ensuring that all threads are complete.
  • If you want to test your code for behavior during parallel execution, it is often useful to first create all Thread and make them work synchronously. Calling await() on a generic CountDownLatch or CyclicBarrier as the first employee instruction will often do this trick quite well.
  • While boolean reading and writing should be atomic according to the Java tutorial , I would recommend declaring trigger variables such as your goOn field should be mutable, as this also affects how the compiler optimizes your code.

Using either volatile or System.exit(0) , your test usually ends.

0
source share

All Articles