00:00

Thread Priority in Java – setPriority, Ranges and Real Behaviour

Last updated: 5 min read

Every Java thread has a priority, an integer from 1 to 10, that hints to the scheduler how important the thread is. In theory, higher-priority threads get CPU time before lower-priority ones. In practice, Java delegates scheduling to the operating system, which may weigh priorities differently or ignore them entirely.

This tutorial covers the priority constants, setPriority() and getPriority(), how priorities are inherited and capped, what happens with virtual threads, and why you should not rely on priorities for correctness.

1. Priority Range and Constants

Java thread priority range from MIN_PRIORITY 1 to MAX_PRIORITY 10
ConstantValueMeaning
Thread.MIN_PRIORITY1Lowest priority
Thread.NORM_PRIORITY5Default for the main thread
Thread.MAX_PRIORITY10Highest priority

2. setPriority() and getPriority()

PriorityBasics.java
public class PriorityBasics {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("MIN_PRIORITY  = " + Thread.MIN_PRIORITY);
        System.out.println("NORM_PRIORITY = " + Thread.NORM_PRIORITY);
        System.out.println("MAX_PRIORITY  = " + Thread.MAX_PRIORITY);
        System.out.println("main thread priority = " + Thread.currentThread().getPriority());

        Thread low = new Thread(() -> { }, "low");
        Thread high = new Thread(() -> { }, "high");
        low.setPriority(Thread.MIN_PRIORITY);
        high.setPriority(Thread.MAX_PRIORITY);
        System.out.println(low.getName() + " = " + low.getPriority() + ", " + high.getName() + " = " + high.getPriority());

        try {
            high.setPriority(11);
        } catch (IllegalArgumentException e) {
            System.out.println("setPriority(11): " + e.getClass().getSimpleName());
        }
    }
}
Output
MIN_PRIORITY  = 1
NORM_PRIORITY = 5
MAX_PRIORITY  = 10
main thread priority = 5
low = 1, high = 10
setPriority(11): IllegalArgumentException

Values outside 1–10 throw IllegalArgumentException. Priority can be changed before or after a thread starts.

3. Inherited Priorities, Thread Groups and Virtual Threads

PriorityInheritance.java
public class PriorityInheritance {
    public static void main(String[] args) throws InterruptedException {
        Thread parent = new Thread(() -> {
            Thread child = new Thread(() -> { });
            System.out.println("child inherits parent's priority: " + child.getPriority());
        });
        parent.setPriority(8);
        parent.start();
        parent.join();

        // A thread group caps the priority of its threads
        ThreadGroup group = new ThreadGroup("background");
        group.setMaxPriority(4);
        Thread t = new Thread(group, () -> { }, "bg-worker");
        t.setPriority(Thread.MAX_PRIORITY);       // silently capped
        System.out.println("bg-worker asked for 10, got: " + t.getPriority());

        // Virtual threads always have NORM_PRIORITY; setPriority has no effect
        Thread v = Thread.ofVirtual().unstarted(() -> { });
        v.setPriority(Thread.MAX_PRIORITY);
        System.out.println("virtual thread priority: " + v.getPriority());
    }
}
Output
child inherits parent's priority: 8
bg-worker asked for 10, got: 4
virtual thread priority: 5
  • A new thread starts with the priority of the thread that created it.
  • A thread's priority is capped by its thread group's maximum priority.
  • Virtual threads always have NORM_PRIORITY; setPriority is ignored for them.

4. Priorities Are Only Hints

Two threads count as fast as they can for half a second, one at priority 10 and one at priority 1:

PriorityRace.java
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;

public class PriorityRace {
    public static void main(String[] args) throws InterruptedException {
        AtomicLong lowCount = new AtomicLong(), highCount = new AtomicLong();
        CountDownLatch go = new CountDownLatch(1);
        Thread low = new Thread(() -> spin(go, lowCount));
        Thread high = new Thread(() -> spin(go, highCount));
        low.setPriority(Thread.MIN_PRIORITY);
        high.setPriority(Thread.MAX_PRIORITY);
        low.start(); high.start();
        go.countDown();
        Thread.sleep(500);
        low.interrupt(); high.interrupt();
        low.join(); high.join();
        System.out.printf("High-priority iterations: %,d%n", highCount.get());
        System.out.printf("Low-priority iterations:  %,d%n", lowCount.get());
    }

    static void spin(CountDownLatch go, AtomicLong counter) {
        try { go.await(); } catch (InterruptedException e) { return; }
        while (!Thread.currentThread().isInterrupted()) counter.incrementAndGet();
    }
}
Output (sample run on a multi-core Mac; results vary)
High-priority iterations: 8,818,105
Low-priority iterations:  128,341,715

On this run the low-priority thread did far more work. With spare cores, both threads run in parallel and priority hardly matters, and the measured difference comes from other factors. How priorities behave depends on the platform:

  • Linux: HotSpot ignores Java priorities by default (all threads get the same OS priority) unless special JVM flags and permissions are used.
  • Windows: Java's 10 levels map onto fewer OS priority levels.
  • macOS: priorities have limited, unpredictable effect.

5. Guidelines

  • Never rely on priority for correctness, such as making one thread run before another. Use join(), latches, queues or CompletableFuture to control ordering.
  • Very high priorities on busy threads can cause starvation of lower-priority threads on platforms that honour them.
  • If some work truly matters more, limit concurrency for less important work instead, for example with a small, separate thread pool.
  • Leave most threads at NORM_PRIORITY.

6. Summary

  • Thread priority is an integer from 1 (MIN_PRIORITY) to 10 (MAX_PRIORITY); the default is 5.
  • Use setPriority() and getPriority(); values outside the range throw an exception.
  • New threads inherit their creator's priority; thread groups cap it; virtual threads ignore it.
  • Priorities are scheduling hints with platform-dependent effects; never use them for program logic.

Related Tutorials