This is a test about thread priority.
The code is from Thinking in Java p.809
import java.util.concurrent.*;
public class SimplePriorities implements Runnable {
private int countDown = 5;
private volatile double d; // No optimization
private int priority;
public SimplePriorities(int priority) {
this.priority = priority;
}
public String toString() {
return Thread.currentThread() + ": " + countDown;
}
public void run() {
Thread.currentThread().setPriority(priority);
while (true) {
// An expensive, interruptable operation:
for (int i = 1; i < 10000000; i++) {
d += (Math.PI + Math.E) / (double) i;
if (i % 1000 == 0)
Thread.yield();
}
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++)
exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
exec.shutdown();
}
}
I wonder why I can't get a regular result like:
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-6,10,main]: 4
Thread[pool-1-thread-6,10,main]: 3
Thread[pool-1-thread-6,10,main]: 2
Thread[pool-1-thread-6,10,main]: 1
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-5,1,main]: 5
Thread[pool-1-thread-4,1,main]: 5
...
but a random result (every time I run it changes):
Thread[pool-1-thread-2,1,main]: 5
Thread[pool-1-thread-3,1,main]: 5
Thread[pool-1-thread-4,1,main]: 5
Thread[pool-1-thread-2,1,main]: 4
Thread[pool-1-thread-3,1,main]: 4
Thread[pool-1-thread-1,1,main]: 5
Thread[pool-1-thread-6,10,main]: 5
Thread[pool-1-thread-5,1,main]: 5
...
I use i3-2350M 2C4T CPU with Win 7 64 bit JDK 7.
Does it matter ?
Java Thread priority has no effect
Thread priorities are highly OS specific and on many operating systems often have minimal effect. Priorities help to order the threads that are in the run queue only and will not change how often the threads are run in any major way unless you are doing a ton of CPU in each of the threads.
Your program looks to use a lot of CPU but unless you have fewer cores than there are threads, you may not see any change in output order by setting your thread priorities. If there is a free CPU then even a lower priority thread will be scheduled to run.
Also, threads are never starved. Even a lower priority thread will given time to run quite often in such a situation as this. You should see higher priority threads be given time sliced to run more often but it does not mean lower priority threads will wait for them to finish before running themselves.
Even if priorities do help to give one thread more CPU than the others, threaded programs are subject to race conditions which help inject a large amount of randomness to their execution. What you should see however, is the max priority thread is more likely to spit out its 0 message more often than the rest. If you add the priority to the println(), that should become obvious over a number of runs.
It is also important to note that System.out.println(...) is synchronized method that is writing IO which is going to dramatically affect how the threads interact and the different threads are blocking each other. In addition, Thread.yield(); can be a no-op depending on how the OS does its thread scheduling.
but a random result (every time I run it changes):
Right. The output from a threaded program is rarely if ever "perfect" because by definition the threads are running asynchronously. We want the output to be random because we want the threads to be running in parallel independently from each other. That is their power. If you expecting some precise output then you should not be using threads.
Thread priority is implementation dependent. In particular, in Windows:
Thread priority isn't very meaningful when all threads are competing
for CPU. (Source)
The book "Java Concurrency in Practice" also says to
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.
Thread priority does not guarantee execution order. It comes into play when resources are limited. If the System is running into constraints due to memory or CPU, then the higher priority threads will run first. Assuming that you have sufficient system resources (which I would assume so for a simple program and the system resources you posted), then you will not have any system constraints. Here is a blog post (not my post) I found that provides more information about it: Why Thread Priority Rarely Matters.
Let's keep it simple and go straight to the source ...
Every thread has a priority. When there is competition for processing
resources, threads with higher priority are generally executed in
preference to threads with lower priority. Such preference is not,
however, a guarantee that the highest priority thread will always be
running, and thread priorities cannot be used to reliably implement
mutual exclusion.
from the Java Language Specification (2nd Edition) p.445.
Also ...
Although thread priorities exist in Java and many references state
that the JVM will always select one of the highest priority threads
for scheduling [52, 56, 89], this is currently not guaranteed by the
Java language or virtual machine specifications [53, 90]. Priorities
are only hints to the scheduler [127, page 227].
from Testing Concurrent Java Components (PhD Thesis, 2005) p. 62.
Reference 127, page 227 (from the excerpt above) is from Component Software: Beyond Object-Oriented Programming (by C. Szyperski), Addison Wesley, 1998.
In short, do not rely on thread priorities.
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.
Jeff Atwood has a good post on the topic: "Thread Priorities are Evil"
Here's the problem. If somebody begins the work that will make 'cond'
true on a lower priority thread (the producer), and then the timing of
the program is such that the higher priority thread that issues this
spinning (the consumer) gets scheduled, the consumer will starve the
producer completely. This is a classic race. And even though there's
an explicit Sleep in there, issuing it doesn't allow the producer to
be scheduled because it's at a lower priority. The consumer will just
spin forever and unless a free CPU opens up, the producer will never
produce. Oops!
As mentioned in other answers, Thread priority is more a hint than a definition of a strict rule.
That said, even if priority would be considered in a strict(er) way, your test-setup would not lead to the result which you describe as "expected". You are first creating 5 threads having equally low priority and one thread having high priority.
The CPU you are using (i3) has 4 native threads. So even if high priory would imply that the thread runs without interruption (which is not true), the low priority threads will get 3/4 of the cpu power (given that no other task is running). This CPU power is allocated to 5 threads, thus the low priority threads will run at 4 * 3/4 * 1/5 = 3/5 times the speed of the high priority thread. After the high priority thread has completed, the low priority threads run at 4/5 of the speed of the high priority thread.
You are launching the low priority threads before the high priority threads. Hence they start a bit earlier. I expect that in most systems "priority" is not implemented down to the nanosecond. So the OS will allow that a threads runs "a little longer" until it switches to another thread (to reduce the impact of switching cost). Hence, the result depends a lot on how that switching is implemented and how big the task is. If the task is small, it could be that no switching will take place, and in your example all the low priority threads finish first.
These calculations assumed that high and low priority where interpreted as extrem cases. In fact, priority is rather something like "in n out of m cases prefer this" with variable n and m.
You have a Thread.yield in your code! This will pass execution to another thread. If you do that too often, it will result in all threads getting equal CPU power.
Hence, I would not expect the output you mentioned in your question, namely that the high priority thread finishes first and then the low priority thread finish.
Indeed: With the line Thread.yield I have the result that each thread get the same CPU time. Without the line Thread.yield and increasing the number of calculations by a factor of 10 and increasing the number of low prio threads by a factor of 10, I get an expected result, namely that the high prio thread finishes earlier by some factor (which depends on the number of native CPU threads).
I believe the OS is free to disregard Java thread priority.
Thread priority is a hint (which can be ignored) such that when you have 100% CPU, the OS know you want to prefer some threads over others. The thread priority must be set before the thread is started or it can be ignored.
On Windows you have to be Administrator to set the thread priority.
Several things to consider:
thread priorities are evil and in most cases they should not be used: http://www.codinghorror.com/blog/2006/08/thread-priorities-are-evil.htmll
you explicitely yield, which probably makes your test invalid
have you checked the generated bytecode? Are you certain that your volatile variable is behaving as you expect it to? Reordering may still happen for volatile variables.
Some OS doesn't provide proper support for Thread priorities.
You have got to understand that different OS deal with thread priorities differently. For example Windows uses a pre-emptive time-slice based scheduler which gives a bigger time slice to higher priority threads where as some other OS (very old ones) use non pre-emptive scheduler where higher priority thread is executed entirely before lower priority thread unless the higher priority thread goes to sleep or does some IO operation etc.
That is why it is not guaranteed that the higher priority thread completely executes, it infact executes for more time than low priority threads so that is why your outputs are ordered in such a way.
In order to know how Windows handles multithreading please refer the below link:
https://learn.microsoft.com/en-us/windows/win32/procthread/multitasking
High-priority thread doesn't stop low-priority thread until it's done. High-priority doesn't make something faster either, if it did, we'd always make everything high-priority. And low-priority doesn't make things slower or we'd never use it.
As I understand you are misunderstanding that rest of the system should be idle and just let the highest-priority thread work while the rest of the system's capacity is wasted.
What I can't find is any statement on whether changing a thread's priority is a costly operation, time-wise. I would like to do it frequently, but if each switch carries a significant time penalty it is probably not worth the trouble.
What I can't find is any statement on whether changing a thread's priority is a costly operation, time-wise. I would like to do it frequently, but if each switch carries a significant time penalty it is probably not worth the trouble.
Any answer here is going to be very OS dependent. I suspect with most Unix variants that the answer is no, it's not costly. It may require some sort of data synchronization but otherwise it is just setting a value on the thread's administrative information. I suspect that there is no rescheduling of the threads as discussed in the comments.
That said, without knowing more about your particular use case, I doubt it is going to be worth the trouble. As I say in the answer listed below, about the only time thread prioritization will make a difference is if all of the threads are completely CPU bound and you want one task or another to get more cycles.
Also, thread priorities are very non-linear and small changes to them may have little to no effect so any overhead incurred in setting the thread priorities will overwhelm any benefits gained by changing them.
See my answer here:
Guide for working with Linux thread priorities and scheduling policies?
Also, check out this article about Java thread priorities and some real life testing of them under Linux. To quote:
As can be seen, thread priorities 1-8 end up with a practically equal share of the CPU, whilst priorities 9 and 10 get a vastly greater share (though with essentially no difference between 9 and 10). The version tested was Java 6 Update 10.
In the case of Windows, a call to SetThreadPriority to change the priority of a ready to run thread is a system call that will move the thread from it's current priority ready queue to a different priority ready queue, which is more costly than just setting some value in a thread object.
If SetThreadPriority is used to increase the priority of a thread, and if that results in the now higher priority thread preempting a lower priority thread, the preemption occurs at call time, not at the next time slice.
Ready queues are mentioned here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682105(v=vs.85).aspx
Context switching related to a priority change is mentioned here: "The following events might require thread dispatching ... A thread’s priority changes, either because of a system service call or because Windows itself changes the priority value." and "Preemption ... a lower-priority thread is preempted when a higher-priority thread becomes ready to run. This situation might occur for a couple of reasons: A higher-priority thread’s wait completes ... A thread priority is increased or decreased." Ready queues are also mentioned: "Windows multiprocessor systems have per-processor dispatcher ready queues"
https://www.microsoftpressstore.com/articles/article.aspx?p=2233328&seqNum=7
I asked about this at MSDN forums. The fourth post agrees with the sequence I mention in the first and third post in this thread:
https://social.msdn.microsoft.com/Forums/en-US/d4d40f9b-bfc9-439f-8a76-71cc5392669f/setthreadpriority-to-higher-priority-is-context-switch-immediate?forum=windowsgeneraldevelopmentissues
In the case of current versions of Linux, run queues indexed by priority were replaced by a red-black tree. Changing a thread's priority would involve removal and reinsertion of a thread object within the red-black tree. Preemption would occur if the thread object is moved sufficiently to the "left" of the red-black tree.
https://www.ibm.com/developerworks/library/l-completely-fair-scheduler
In response to the comments about the app that "examines a full-speed stream of incoming Bluetooth data packets", the receiving thread should be highest priority, hopefully spending most of its time not running while waiting for the reception of a packet. The high priority packets would be queued up to be processed by another thread just lower in priority than the receiving thread. Multiple processing threads could take advantage of multiple cores if needed.
I read that the correctness of thread priority algorithm is not always guaranteed beacause it depends on the JVM. Why is so and how does it depend on the JVM?
Thanks in advance.
The thread priorities effect is platform specific. Playing with these priorities should be avoided as they can cause liveness problems and their effect is not obvious.
From the Java Concurency in practice:
The thread priorities defined in the Thread API are merely scheduling hints.The Thread
API defines ten priority levels that the JVM can map to operating system scheduling
priorities as it sees fit. This mapping is platform‐specific, so two Java priorities
can map to the sameOS priority on one system and different OS priorities on another.
...
The thread priority mechanism is a blunt instrument, and it's not always obvious what
effect changing priorities will have; boosting a thread's priority might do nothing or
might always cause one thread to be scheduled in preference to the other, causing
starvation.
Conclusion:
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.
What does thread priority means? will a thread with MAX_PRIORITY completes its execution before a thread which has MIN_PRIORITY? Or a MAX_PRIORITY thread will be given more execution time then MIN_PRIORITY thread? or any thing else?
The javadoc for Thread only says this, "Threads with higher priority are executed in preference to threads with lower priority." That can mean different things depending on what JVM you are running and, more likely, on what operating system you are running.
In the simplest interpretation of "priority", as implemented by some real-time, embedded operating systems; a thread with a lower priority will never get to run when a higher priority thread is waiting to run. The lower priority thread will be immediately preempted by whatever event caused the higher priority thread to become runnable. That kind of absolute priority is easy to implement, but it puts a burden on the programmer to correctly assign priorities to all of the different threads of all of the different processes running in the box. That is why you usually don't see it outside of embedded systems.
Most general-purpose operating systems assume that not all processes are designed to cooperate with one another. They try to be fair, giving an equal share to each thread that wants CPU time. Usually that is accomplished by continually adjusting the thread's true priorities according to some formula that accounts for how much CPU different threads have wanted in the recent past, and how much each got. There usually is some kind of a weighting factor, to let a programmer say that this thread should get a larger "share" than that thread. (e.g., the "nice" value on a Unix-like system.)
Because any practical JVM must rely on the OS to provide thread scheduling, and because there are so many different ways to interpret"priority"; Java does not attempt to dictate what "priority" really means.
According to my understanding(which may be incorrect. Kindly correct me if it is so), thread scheduler(or thread dispatcher) is the one who will decide which thread gets the CPU time (when multiple threads are competing for the CPU). This thread scheduler is OS dependent. Thread scheduler can use either time slicing algorithm or preemptive algorithm or something else. If the underlying OS's thread scheduler uses time slicing algorithm, then setting high/low priority for a thread using JAVA's Thread.setHightPriority() method will have any impact at all ?
If yes, then how can it make an impact on the underlying OS's thread scheduler ?
If not, then what is the point of having Thread.setPriority() method in this case ? Should the java developer be aware of on which OS this application will be running and if that OS uses preemptive multithreading then only go for Thread.setPriority() ?
Any thoughts on this is much appreciated ?
Thanks.
If the underlying OS's thread scheduler uses time slicing algorithm, then setting high/low priority for a thread using JAVA's Thread.setHightPriority() method will have any impact at all ?
Yes. Why do you think it won't?
If yes, then how can it make an impact on the underlying OS's thread scheduler?
Because time slices can still be allocated in priority order. You seem to be assuming this is impossible. Why?
Should the java developer be aware of on which OS this application will be running and if that OS uses preemptive multithreading then only go for Thread.setPriority() ?
No, and you haven't disclosed your actual reasons for thinking otherwise.
In any case, priorities are only hints to the scheduler, they cannot be relied upon.
Every thread has a priority. When there is competition for processing
resources, threads with higher priority are generally executed in
preference to threads with lower priority. Such preference is not,
however, a guarantee that the highest priority thread will always be
running, and thread priorities cannot be used to reliably implement
mutual exclusion.
from the Java Language Specification (2nd Edition) p.445.
Also ...
Although thread priorities exist in Java and many references state
that the JVM will always select one of the highest priority threads
for scheduling [52, 56, 89], this is currently not guaranteed by the
Java language or virtual machine specifications [53, 90]. Priorities
are only hints to the scheduler [127, page 227].
from Testing Concurrent Java Components (PhD Thesis, 2005) p. 62.
Reference 127, page 227 (from the excerpt above) is from Component Software: Beyond Object-Oriented Programming (by C. Szyperski), Addison Wesley, 1998.
In short, do not rely on thread priorities.