12

Can anybody explain how thread priority works in java. The confusion here is if java does'nt guarantee the implementation of the Thread according to its priority then why is this setpriority() function used for.

My code is as follows :

public class ThreadSynchronization implements Runnable{

    public synchronized void run() {
        System.out.println("Starting Implementation of Thread "+Thread.currentThread().getName());
        for(int i=0;i<10;i++)
        {
            System.out.println("Thread "+Thread.currentThread().getName()+" value : "+i);
        }
        System.out.println("Ending Implementation of Thread "+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        System.out.println("Program starts...");
        ThreadSynchronization th1 = new ThreadSynchronization();
        Thread t1 = new Thread(th1);
        t1.setPriority(1);
        synchronized(t1)
        {
            t1.start();
        }

        ThreadSynchronization th2 = new ThreadSynchronization();
        Thread t2 = new Thread(th2);
        t2.setPriority(9);
        synchronized (t2) {
            t2.start(); 
        }

        System.out.println("Program ends...");
    }
}

In the above program even if I change the priority I find no difference in the output. Also a real time application of how thread priority can be used would be of great help. Thanks.

Trying
  • 14,004
  • 9
  • 70
  • 110
Neal
  • 537
  • 2
  • 12
  • 23
  • Two useful links (in case you haven't seen them yet): http://www.javamex.com/tutorials/threads/priority.shtml and http://www.javamex.com/tutorials/threads/priority_what.shtml . – PM 77-1 Dec 02 '13 at 16:44
  • This might help: http://stackoverflow.com/questions/1617963/setting-priority-to-javas-threads?rq=1 – Tilak Madichetti May 11 '16 at 13:18

6 Answers6

11

Thread priority is just a hint to OS task scheduler and is dependent on the underlying OS. OS will try to allocate more resources to a high priority thread but it does not guarantee it. So if your program is dependent on thread priorities than you are in-turn binding your program to underlying OS, which is bad.

From Java Concurrency in Practice:

Avoid the temptation to use thread priorities, since they increase platform dependence and can cause liveness problems. Most concurrent applications can use the default priority for all threads.

Trying
  • 14,004
  • 9
  • 70
  • 110
  • 1
    That remark is flat wrong. There are many situations where setting a priority is a good thing. Even if some OSes then will ignore that hint, it is still better to have the code run smoother on the other OSes. What's bad is to base your code on false assumptions, like that the order of thread execution is in any way deterministic. – TwoThe Dec 02 '13 at 17:14
  • 3
    @TwoThe Read the book that i have mentioned before commenting like this. – Trying Dec 02 '13 at 18:24
  • Although it's been said over and over again, not to use priorities for threads. I would love to see an "official" statement about this from Oracle. (Maybe there is, but I clearly missed it) In contrast, the Oracle concurrency tutorials use thread priorities all the time. – bvdb Jan 07 '16 at 08:57
  • @bvdb The people who wrote the book quoted in this answer are the ones who have designed all the concurrency packages in the JDK, one of them (Brian Goetz) being Java language architect... That's as official as it gets. And note that they don't say "never use priorities" - they only say that priorities are difficult to use properly and that an incorrect usage may lead to starvation issues on certain platforms. – assylias Jul 25 '17 at 14:31
5

Thread priority is only a hint to OS task scheduler. Task scheduler will only try to allocate more resources to a thread with higher priority, however there are no explicit guarantees.

In fact, it is not only relevant to Java or JVM. Most non-real time OS use thread priorities (managed or unmanaged) only in a suggestive manner.

Also very important, Priorties are different to every underlying plattform. Therefore you kind of loose your plattform freedom of java. See this summary as well:

Indeed, some priority levels can map to the same "native" priority level. Here's the list (based on the Hotspot code in OpenJDK 6):

Solaris
1 ⇒ 0
2 ⇒ 32
3 ⇒ 64
4 ⇒ 96
5 – 10 ⇒ 127
Of note is that on Solaris, you can't raise the thread priority above normal, only lower it: the priority value for 5 is the same as any of the higher values.

Linux
1 – 10 ⇒ 4 – -5 (nice values) Of note is that on Linux, different thread priorities in Java do map to distinct priority values at native level.

Windows
1 – 2 ⇒ THREAD_PRIORITY_LOWEST
3 – 4 ⇒ THREAD_PRIORITY_BELOW_NORMAL
5 – 6 ⇒ THREAD_PRIORITY_NORMAL
7 – 8 ⇒ THREAD_PRIORITY_ABOVE_NORMAL
9 – 10 ⇒ THREAD_PRIORITY_HIGHEST

I've developed a lot of multi threaded java applications, and in my opinion if you have to set thead priorities you have another problem. Like a bad algorythm that consumes to much cpu time etc.... I always suggest to not change the java thread prio, since you can't rely on it anyways. (of course there are some scenarios where it makes sense)

Colin
  • 101
  • 8
  • I have read somewhere in java doc that if a higher priority thread takes control over a lower priority thread then there are chances that the lower priority thread may die.. Can you explain me taking the Windows platform, that if I change the priority of thread will it affect the execution of the threads ? – Neal Dec 02 '13 at 16:55
  • W.R.T your last statement (of course there are some scenarios where it makes sense). Can you give me one such scenario where it makes sense ? – Neal Dec 02 '13 at 17:07
  • Sure. First to your second comment. When does it make sense? No Sense: An easy rule, if you have programmed something and you think: hm it's slow. Ok let me change Thread-Prio, that's in 99% of all cases just wrong and won't speed up your programm. Sense (1 Scenario out of 1000, there are lot of examples): I have two kind of Threads. 1 Thread is my Managerthread and 1 is a stupid worker Thread. I create 1Mio Worker Threads and 1 MngThread. In MgnThread can stop Workerthreads. Now it makes sense to set MngThread to High Prio! So that he can immediately stop worker Threads. See my point? ;) – Colin Dec 02 '13 at 21:49
  • To your first comment I don't really understand the question. 1st, yes setting a thread to higher prio can lead to other threads starving (they never get any cpu time, because the higher priorised thread uses all the cpu time). On Windows. Yes if you make everything correct and you have a programm that can benefit from more cpu time, then threads with higher prio finish faster. Be carefull. 1st as you can see above, on Windows, always change by 2, otherwhise you are still in the same Win.ThreadPrioCategory and nothing changes. 2nd you won't notice a difference in very short executing threads – Colin Dec 02 '13 at 22:00
1

There are several situations where setting a priority for a Thread is useful, you just must not start believing in any guarantees that come form such settings, as always: the order of execution with threads is undefined. If you think that your thread will be done earlier if you give it a higher priority, please read the statement above again until that's out of your head. ;)

You should define the priority based on how important it is for this thread to gain execution time compared to the others. Even though the underlaying system guarantees nothing, it still can provide a benefit for those JVMs that support it.

Example: You have a program that does some heavy calculation based on user input in your JFrame. It is a good practice to set those background threads to a low priority, because it is more important that the JFrame is responsive than working on the calculation (which will take a long time to finish anyways, a few more millis won't hurt). The OS will still assign most CPU time to the low priority threads, unless something more important needs it. But then it is good that this more important stuff gets the priority.

Now it could happen that on some systems the priority setting is ignored and the JFrame is again unresponsive, but then this does nothing worse to your code then not setting the priority to low in the first place.

TwoThe
  • 13,879
  • 6
  • 30
  • 54
1

The size of the tasks is too small and probably will complete right after the start. Also, if you have "enough" CPU cores, each worker thread will be allocated to one core, so the result will be the same.

Try the experiment in a different context, first increase the task size (for example by looping one thousand times to one million, without print) then increase the number of threads to exceed the number of cores you have and third, create your threads first and then start all the threads (you cannot start them at once, you will still need to loop through them).

In my case, I have chosen 10 threads because I ran the code on a processor with two hyper-threaded cores, running four simultaneous threads.

My changes to your example:

public class ThreadPriority implements Runnable {

    public synchronized void run() {
        System.out.println("Starting Implementation of Thread " + Thread.currentThread().getName());
        float s = 0;
        for (int i = 0; i < 1000; i++)
            for (int k = 0; k < 1000000; k++)
                s += k;
        System.out.println("Ending Implementation of Thread " + Thread.currentThread().getName() + " " + s);
    }

    Thread t;

    public ThreadPriority(String name, int prio) {
        t = new Thread(this);
        t.setName(name);
        t.setPriority(prio);
    }

    public void start() {
        synchronized (t) {
            t.start();
        }
    }

    public static void main(String[] args) {
        System.out.println("Program starts...");
        ThreadPriority[] th = new ThreadPriority[10];
        for (int i = 0; i < th.length; i++) {
            th[i] = new ThreadPriority("T" + i, i / 2 + 1);
        }

        for (ThreadPriority tp : th)
            tp.start();

        System.out.println("Program ending, wait for all the threads to complete");
    }
}

Results are:

Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T9
Starting Implementation of Thread T8
Starting Implementation of Thread T5
Program ending, wait for all the threads to complete
Starting Implementation of Thread T4
Starting Implementation of Thread T6
Starting Implementation of Thread T7
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Starting Implementation of Thread T1
Ending Implementation of Thread T6 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13

As you can see, the low number threads tend to end later, because the high number threads have higher priority. By turning the scale upside down:

    for (int i = 0; i < th.length; i++) {
        th[i] = new ThreadPriority("T" + i, 9 - i / 2 );
    }

The low number threads complete faster than the high ones. Some threads complete even before other threads are started, because they have higher priority compared to the calling program:

Program starts...
Starting Implementation of Thread T0
Starting Implementation of Thread T1
Starting Implementation of Thread T2
Starting Implementation of Thread T3
Program ending, wait for all the threads to complete
Ending Implementation of Thread T2 1.7592186E13
Ending Implementation of Thread T3 1.7592186E13
Ending Implementation of Thread T0 1.7592186E13
Ending Implementation of Thread T1 1.7592186E13
Starting Implementation of Thread T9
Starting Implementation of Thread T4
Starting Implementation of Thread T8
Starting Implementation of Thread T7
Starting Implementation of Thread T5
Starting Implementation of Thread T6
Ending Implementation of Thread T4 1.7592186E13
Ending Implementation of Thread T5 1.7592186E13
Ending Implementation of Thread T7 1.7592186E13
Ending Implementation of Thread T8 1.7592186E13
Ending Implementation of Thread T9 1.7592186E13
Ending Implementation of Thread T6 1.7592186E13
-1

Hope it helps!

package priority;

public class ThreadPriorityApp {

    // Note : Thread priority may not be supported in some OS due to underlying task scheduler at OS level

    /**
     * MyThread is an inner class implementing Thread functionality
     *
     */
    class MyThread extends Thread {

        public MyThread(String threadName) {
            super(threadName);
        }
        public void run() {
            System.out.println("Running  thread - " + Thread.currentThread().getName());
        }
    }

    public static void main(String[] args) {

        //If priority is not set then main priority is set to threads created inside main thread - Parent to child
        // Main thread priority - 5, is set to Thread 1 and Thread 2, if not manually assigned (commenting Line #34 and #35)
        System.out.println("Main thread priority - " + Thread.currentThread().getPriority());

        ThreadPriorityApp threadPriorityApp = new ThreadPriorityApp();

        //We are creating two threads
        MyThread th = threadPriorityApp.new MyThread("Thread 1");
        MyThread th2 = threadPriorityApp.new MyThread("Thread 2");

        // Range 1 to 10 - 10 being given as MAX Priority
        th.setPriority(Thread.MIN_PRIORITY);
        th2.setPriority(Thread.MAX_PRIORITY);

        //We have started Thread 1 first and then Thread 2 later
        th.start();
        th2.start();

//      Possible Outcomes(1) (With Priority - Line #34 and #35) :
//      Running  thread - Thread 2
//      Running  thread - Thread 1


//      Possible Outputs(2) : (Without Priority - commenting Line #34 and #35)
//      (1) Running  thread - Thread 1
//          Running  thread - Thread 2
//      OR
//      (2) Running  thread - Thread 2
//          Running  thread - Thread 1

    }

    //Happy coding -- Parthasarathy S
}
Parthasarathy S
  • 197
  • 1
  • 6
-2
 //The iterative and recursive with memorize both shows count as 1424 for digits of length ten starting with 1.
 int[][] b = {{4,6},{6,8},{7,9},{4,8},{0,3,9},{},{1,7,0},{2,6},{1,3},{2,4}};
 public int countIterative(int digit, int length) {
    int[][] matrix = new int[length][10];
    for(int dig =0; dig <=9; dig++){
          matrix[0][dig] = 1;
    }
    for(int len = 1; len < length; len++){
        for(int dig =0; dig <=9; dig++){
          int sum = 0;
          for(int i : b[dig]){
            sum += matrix[len-1][i];
          }
          matrix[len][dig] = sum;
        }
    }
    return matrix[length-1][digit];
}
public int count(int index, int length, int[][] matrix ){
    int sum = 0;
    if(matrix[length-1][index] > 0){
       return matrix[length-1][index];
    }
    if( length == 1){
        return 1;
    }
    for(int i: b[index] )  {
         sum += count(i, length-1,matrix);
    }
    matrix[length-1][index] = sum;
    return sum;
}
navin
  • 9
  • 1
  • Welcome to StackOverflow! Thank you for your submission! While this code may solve the Original Poster's problem, could you please provide some explanation as to how you addressed the problem? This will help future readers of this question if they have similar problems. – gariepy Apr 04 '16 at 15:48