Thread Priority in Java – setPriority, Ranges and Real Behaviour
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
| Constant | Value | Meaning |
|---|---|---|
Thread.MIN_PRIORITY | 1 | Lowest priority |
Thread.NORM_PRIORITY | 5 | Default for the main thread |
Thread.MAX_PRIORITY | 10 | Highest priority |
2. setPriority() and getPriority()
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());
}
}
}
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
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());
}
}
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;setPriorityis 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:
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();
}
}
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 orCompletableFutureto 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()andgetPriority(); 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
Frequently Asked Questions (FAQ)
Q1. What is thread priority in Java?
An integer from 1 to 10 that hints to the scheduler how important a thread is relative to others.
Q2. What is the default priority of a thread?
The main thread has NORM_PRIORITY (5). Other threads inherit the priority of the thread that created them.
Q3. What happens if I set a priority greater than 10?
setPriority throws IllegalArgumentException.
Q4. Does a higher priority guarantee earlier execution?
No. Scheduling is done by the operating system, which may treat priorities as weak hints or ignore them.
Q5. How do I get a thread's priority?
Call thread.getPriority().
Q6. Can I change priority after starting a thread?
Yes. setPriority can be called at any time, though its effect is still platform-dependent.
Q7. Do child threads inherit priority?
Yes. A new platform thread starts with the same priority as the thread that created it.
Q8. What is the priority of a virtual thread?
Always NORM_PRIORITY. Calls to setPriority on virtual threads have no effect.
Q9. Does Linux honour Java thread priorities?
Not by default with HotSpot. All Java threads get the same OS scheduling priority unless special options and privileges are used.
Q10. What is thread starvation?
When a thread rarely or never gets CPU time or a lock, for example because higher-priority threads keep the CPU busy.
Q11. Can two threads have the same priority?
Yes. Most threads share NORM_PRIORITY, and the scheduler shares CPU time among them.
Q12. How does a thread group affect priority?
A thread's priority cannot exceed its group's maximum priority; higher requests are silently reduced.
Q13. Should I use priorities to order thread execution?
No. Use explicit coordination such as join(), CountDownLatch, BlockingQueue or CompletableFuture.
Q14. Do daemon threads have lower priority?
Not automatically. Daemon status and priority are independent settings.
Q15. How do I set priority for threads in a thread pool?
Provide a custom ThreadFactory that calls setPriority on each new thread, for example via Thread.ofPlatform().priority(3).factory().
Q16. What is preemptive scheduling?
Scheduling where the OS can pause a running thread at any time to run another, typically based on time slices and priority. Modern JVMs rely on it.
Q17. What is time slicing?
Giving each runnable thread a short period of CPU time in turn, so threads of equal priority share the CPU fairly.
Q18. Is thread priority useful at all?
Occasionally, for background work on platforms that honour it, such as Windows desktop applications. On servers it rarely has a measurable effect.
Q19. What priority does the garbage collector run at?
GC threads are internal JVM threads; their scheduling is managed by the JVM and OS and cannot be changed with setPriority.
Q20. Does yield() relate to priority?
Thread.yield() hints that the current thread may give up the CPU to others, typically of the same priority. Like priorities, it is only a hint.