Thread PrioritiesS2C Home « Thread Priorities

In this lesson we investigate thread priorities and how we can have the priority set automatically by the invoking thread or assign thread priorities ourselves using methods of the Thread class. By setting a threads priority higher, we can hopefully make this thread receive more of our processors time than lower priority threads. Setting a threads priority is no guarantee that the thread does in fact receive more CPU time as other factors such as waiting for resources may affect the higher priority threads performance. Also the way the underlying operating system implements multitasking may also affect thread performance and a lower priority thread might under some conditions actually get more CPU time than a higher priority thread. Generally speaking though, threads with higher priorities will get more CPU time than lower priority threads.

The priority ranges we can give a thread have to fall in the ranges of two class constants within the Thread class, namely MIN_PRIORITY and MAX_PRIORITY. At the time of writing these values are set to 1 and 10 respectively. We can also reassign a thread priority back to the default rating using the NORM_PRIORITY value, which at the time of writing has a value of 5.

Thread Methods OverviewTop

The table below shows the declarations of the fields and methods of the Thread class used in this lesson:

Field Declaration Description
public static final int MIN_PRIORITYMinimum priority a thread can have which is currently set at 1.
public static final int MAX_PRIORITYMaximum priority a thread can have which is currently set at 10.
Method Declaration Description
public final int getPriority()Return the priority of this thread.
public final void join()Waits for current thread to die.
public void run()If this thread was constructed using a subclass of the Thread class this method does nothing and should be overridden in the subclass.
If this thread was constructed using a separate Runnable run object, then that Runnable object's run() method is called.
public void start()The JVM calls the run() method of this thread, so it can begin execution.
public static void yield()Will cause the currently executing thread to temporarily pause and allow other threads a chance to execute.

We will go through the methods mentioned above in much greater detail as we go through this lesson. Use the links in the table above to go to the code example where the method is first used.

Same Thread Priority ExampleTop

To see the possible impact of prioritizing threads lets take a look at running multiple threads without any preset priorities. In this scenario all the threads will default to the thread priority of the thread they were started from. As we are just creating these threads from the main user thread, all these threads will also be user threads and have a default priority set, which is 5.


/*
  Multiple threads with some counters to see which threads get the most CPU action
*/
public class TestNoPrioritySet implements Runnable {
    static boolean finish = false; 
    int count = 0;
    
    // Override run() method of Runnable interface to execute a new thread
    public void run() {
        do {
            count++;
        } while (finish == false && count < 9999);
        finish = true;  // Ensure we stop when first thread hits count
    }
    
    public static void main(String[] args) {
        // Create 3 new Runnables
        TestNoPrioritySet tnps1 = new TestNoPrioritySet();
        TestNoPrioritySet tnps2 = new TestNoPrioritySet();
        TestNoPrioritySet tnps3 = new TestNoPrioritySet();
        // Create 3 new threads
        Thread th1 = new Thread(tnps1);
        Thread th2 = new Thread(tnps2);
        Thread th3 = new Thread(tnps3);
        // Check thread priorities
        System.out.println("th1 thread priority = " + th1.getPriority());
        System.out.println("th2 thread priority = " + th2.getPriority());
        System.out.println("th3 thread priority = " + th3.getPriority());
        th1.start();
        th2.start();
        th3.start();
        // Join threads together
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException ex) {
            System.out.println(ex);
        } 
        System.out.println("tnps1 count = " + tnps1.count);
        System.out.println("tnps2 count = " + tnps2.count);
        System.out.println("tnps3 count = " + tnps3.count);
    }
}

Save, compile and run the TestNoPrioritySet class in directory   c:\_Concurrency in the usual way.

test no priority set

In the screenshot above we have run the program three times and the totals are fairly evenly spread between the three threads. All the threads inherit the thread priority from the main thread which is set by the JVM to the default which is 5. We use the getPriority() method to prove this and print the thread priorities out.

The totals you get out will certainly differ each time you run the programs and depend on several factors such as your CPU and how it deals with threads, what is running on your computer at the time and how the scheduler is set up.

As mentioned above thread priorities are no guarantee that a higher priority thread will get more CPU time so it is definitely inadvisable to base thread usage and your coding on priorities. You can of course use thread priorities to take advantage of priority scheduling if it is available, just don't rely on it.

Different Thread Priority ExampleTop

To see the possible impact of prioritizing threads lets take a look at running multiple threads where we set one thread to the smallest priority and another two to the maximum priority.


/*
  Multiple threads with some counters to see which threads get the most CPU action
*/
public class TestPriority implements Runnable {
    static boolean finish = false; 
    int count = 0;
    
    // Override run() method of Runnable interface to execute a new thread
    public void run() {
        do {
            count++;
        } while (finish == false && count < 9999);
        finish = true;  // Ensure we stop when first thread hits count
    }
    
    public static void main(String[] args) {
        // Create 3 new Runnables
        TestPriority tp1 = new TestPriority();
        TestPriority tp2 = new TestPriority();
        TestPriority tp3 = new TestPriority();
        // Create 3 new threads
        Thread th1 = new Thread(tp1);
        Thread th2 = new Thread(tp2);
        Thread th3 = new Thread(tp3);
        // Set thread priorities
        th1.setPriority(Thread.MIN_PRIORITY);
        th2.setPriority(Thread.MAX_PRIORITY);
        th3.setPriority(Thread.MAX_PRIORITY);
        // Check thread priorities
        System.out.println("th1 thread priority = " + th1.getPriority());
        System.out.println("th2 thread priority = " + th2.getPriority());
        System.out.println("th3 thread priority = " + th3.getPriority());
        th1.start();
        th2.start();
        th3.start();
        // Join threads together
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException ex) {
            System.out.println(ex);
        } 
        System.out.println("tp1 count = " + tp1.count);
        System.out.println("tp2 count = " + tp2.count);
        System.out.println("tp3 count = " + tp3.count);
    }
}

Save, compile and run the TestPriority class in directory   c:\_Concurrency in the usual way.

test priority

In the screenshot above we have run the program three times and the results are fairly inconsistent. On my machine I ran this program many times and there was no guarantee that the higher priority threads got any favourable CPU usage.

This program shows that thread priorities are no guarantee that a higher priority thread will get more CPU time so it is definitely inadvisable to base thread usage and code on thread priorities. You can of course use thread priorities to take advantage of priority scheduling if it is available, just don't rely on it.

The yield() MethodTop

The static yield() method puts the currently running thread back to a runnable state to allow other threads of the same priority a chance to run. Although this sounds a great way to use thread prioritisation and allow equal usage of the CPU in reality there is no guarantee that this will actually happen. What we can guarantee is that the yield() method puts the currently running thread back to a runnable state. After this happens which thread gets chosen by the scheduler is out of our hands and it is very possible that the yielding thread is selected again and goes straight back to executing. Lets have a look at how we can use the yield() method:


/*
  Multiple threads with some counters and yields to see which threads get the most CPU action
*/
public class TestPriorityYield implements Runnable {
    static boolean stop = false; 
    int count = 0;
    
    // Override run() method of Runnable interface to execute a new thread
    public void run() {
        do {
            count++;
            // Yield ON ALL threads
            Thread.yield();
        } while (stop == false && count < 9999);
        stop = true;  // Ensure we stop when first thread hits count
    }
    
    public static void main(String[] args) {
        // Create 3 new Runnables
        TestPriorityYield tpy1 = new TestPriorityYield();
        TestPriorityYield tpy2 = new TestPriorityYield();
        TestPriorityYield tpy3 = new TestPriorityYield();
        // Create 3 new threads
        Thread th1 = new Thread(tpy1, "th1");
        Thread th2 = new Thread(tpy2, "th2");
        Thread th3 = new Thread(tpy3, "th3");
        // Set thread priorities
        th1.setPriority(Thread.MIN_PRIORITY);
        th2.setPriority(Thread.MAX_PRIORITY);
        th3.setPriority(Thread.MAX_PRIORITY);
        // Check thread priorities
        System.out.println("th1 thread priority = " + th1.getPriority());
        System.out.println("th2 thread priority = " + th2.getPriority());
        System.out.println("th3 thread priority = " + th3.getPriority());
        th1.start();
        th2.start();
        th3.start();
        // Join threads together
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException ex) {
            System.out.println(ex);
        } 
        System.out.println("tpy1 count = " + tpy1.count);
        System.out.println("tpy2 count = " + tpy2.count);
        System.out.println("tpy3 count = " + tpy3.count);
    }
}

Save, compile and run the TestPriorityYield class in directory   c:\_Concurrency in the usual way.

test yield method

In the screenshot above we have run the program three times and the totals are fairly evenly spread between the three threads. Even though we are using the yield() method it seems to make little difference to which thread becomes runnable after a thread has yielded control.

We will adjust the above code slightly to check the priority value and then yield for threads with a priority of 1.


/*
  Multiple threads with some counters and yield on low priority thread only
*/
public class TestLowPriorityYield implements Runnable {
    static boolean stop = false; 
    int count = 0;
    
    // Override run() method of Runnable interface to execute a new thread
    public void run() {
        do {
            count++;
            // Yield on low priority thread ONLY
            if (Thread.currentThread().getPriority() == 1) {
                Thread.yield();
            }
        } while (stop == false && count < 9999);
        stop = true;  // Ensure we stop when first thread hits count
    }
    
    public static void main(String[] args) {
        // Create 3 new Runnables
        TestLowPriorityYield tlpy1 = new TestLowPriorityYield();
        TestLowPriorityYield tlpy2 = new TestLowPriorityYield();
        TestLowPriorityYield tlpy3 = new TestLowPriorityYield();
        // Create 3 new threads
        Thread th1 = new Thread(tlpy1, "th1");
        Thread th2 = new Thread(tlpy2, "th2");
        Thread th3 = new Thread(tlpy3, "th3");
        // Set thread priorities
        th1.setPriority(Thread.MIN_PRIORITY);
        th2.setPriority(Thread.MAX_PRIORITY);
        th3.setPriority(Thread.MAX_PRIORITY);
        // Check thread priorities
        System.out.println("th1 thread priority = " + th1.getPriority());
        System.out.println("th2 thread priority = " + th2.getPriority());
        System.out.println("th3 thread priority = " + th3.getPriority());
        th1.start();
        th2.start();
        th3.start();
        // Join threads together
        try {
            th1.join();
            th2.join();
            th3.join();
        } catch (InterruptedException ex) {
            System.out.println(ex);
        } 
        System.out.println("tlpy1 count = " + tlpy1.count);
        System.out.println("tlpy2 count = " + tlpy2.count);
        System.out.println("tlpy3 count = " + tlpy3.count);
    }
}

Save, compile and run the TestLowPriorityYield class in directory   c:\_Concurrency in the usual way.

test low priority yield

In the screenshot above we have run the program three times and the totals for the higher priority threads are always higher. In this very contrived example we always yield on the 'th1' thread as it is the only thread with a priority of 1. In fact I ran this code many times and the 'th1' thread was always the lowest due to yielding. To do this we are relying on a threads priority which isn't really a reliable or good practice. Thread priorities are no guarantee that a higher priority thread will get more CPU time so it is definitely inadvisable to base thread usage and your code on priorities as we have done here.

Lesson 4 Complete

In this lesson we investigated thread priorities and how we can have the priority set automatically by the invoking thread or assign thread priorities ourselves using methods of the Thread class.

What's Next?

In our final lesson of the section we explore how threads can communicate with each other when they are within a synchronized method or code block.

go to home page Homepage go to top of page Top