Java Programming Tutorials

Java programming tutorials with many code examples!

Java Thread priority

Problem:

How Java Thread priority works? Is it interpreted at all? In this post we’ll show how setting priorities affects threads execution.

Solution:

java.lang.Thread class have methods that allow to operate on thread priorities. setPriority(int) allow to change thread’s priority (usually from NORMAL_PRIORITY) to some other value.

In the following example we create 10 threads that are busy with some computation. We set MIN_PRIORITY to the first one and MAX_PRIORITY to the last one. See how it works on my machine (GNU/Linux):

package com.farenda.java.lang;

public class ThreadPriority {

    private static class Counter extends Thread {

        private static int threads = 0;
        private int id = ++threads;
        private int loops = 100_000;
        private long startMillis;

        public Counter(long startMillis) {
            this.startMillis = startMillis;
        }

        @Override
        public void run() {
            if (id == 1) {
                setPriority(MIN_PRIORITY);
            } else if (id == 10) {
                setPriority(MAX_PRIORITY);
            }

            while (loops-- >= 0) {
                process(loops);
                Thread.yield();
            }

            System.out.printf("Thread %d (priority %d) done after: %d%n",
                    id, currentThread().getPriority(),
                    System.currentTimeMillis() - startMillis);
        }

        private long process(int x) {
            int sum = 0;
            for (int i = 0; i < x; ++i) {
                sum += i * Math.PI;
            }
            return sum;
        }
    }

    public static void main(String&#91;&#93; args) {
        long startMillis = System.currentTimeMillis();
        Counter&#91;&#93; counters = {
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis),
                new Counter(startMillis)
        };

        System.out.println("Starting counters:");
        for (Counter c : counters) {
            c.start();
        }

        System.out.println("Main thread done after: " +
                (System.currentTimeMillis() - startMillis));
    }
}
&#91;/sourcecode&#93;

<p> Running the code produces the following output: </p>


Starting counters:
Main thread done after: 55
Thread 3 (priority 5) done after: 56854
Thread 1 (priority 1) done after: 86493
Thread 2 (priority 5) done after: 87332
Thread 7 (priority 5) done after: 89398
Thread 10 (priority 10) done after: 91851
Thread 4 (priority 5) done after: 97830
Thread 9 (priority 5) done after: 102316
Thread 5 (priority 5) done after: 104185
Thread 8 (priority 5) done after: 109207
Thread 6 (priority 5) done after: 113975

I run that code a few times and always one thread finished much sooner than others. Here’s result of running the same code, but without Thread.yield():

Starting counters:
Main thread done after: 100
Thread 5 (priority 5) done after: 57121
Thread 10 (priority 10) done after: 84208
Thread 3 (priority 5) done after: 87978
Thread 7 (priority 5) done after: 90503
Thread 8 (priority 5) done after: 94611
Thread 9 (priority 5) done after: 97762
Thread 2 (priority 5) done after: 100027
Thread 6 (priority 5) done after: 104389
Thread 4 (priority 5) done after: 106396
Thread 1 (priority 1) done after: 109485

As you can see there is really no difference.

And another run, but this time, when all threads but one have been set to MIN_PRIORITY:

Starting counters:
Main thread done after: 12
Thread 5 (priority 1) done after: 57951
Thread 2 (priority 1) done after: 88227
Thread 6 (priority 1) done after: 93241
Thread 4 (priority 1) done after: 94999
Thread 10 (priority 10) done after: 99805
Thread 3 (priority 1) done after: 100993
Thread 7 (priority 1) done after: 104988
Thread 9 (priority 1) done after: 107884
Thread 8 (priority 1) done after: 110126
Thread 1 (priority 1) done after: 112575

Setting thread priority doesn’t mean that Thread Scheduler will run thread with the highest priority. It all depends on underlaying platform and is not portable.

Moreover Thread.yield and Thread.setPriority are merely hints to the Thread Scheduler and can be ignored by it! To quote “Effective Java, 2nd” by Josh Bloch: Thread priorities are among the least portable features of the Java platform.

Share with the World!