|
Priority
The priority of a thread tells the scheduler how important this thread is. Although the order that the CPU attends to an existing set of threads is indeterminate, if there are a number of threads blocked and waiting to be run, the scheduler will lean toward the one with the highest priority first. However, this doesn’t mean that threads with lower priority aren’t run (that is, you can’t get deadlocked because of priorities). Lower priority threads just tend to run less often.
Here’s SimpleThread.java modified so that the priority levels are demonstrated. The priorities are adjusting by using Thread’s setPriority( ) method.
//: c13:SimplePriorities.java
// Shows the use of thread priorities.
import com.bruceeckel.simpletest.*;
public class SimplePriorities extends Thread {
private static Test monitor = new Test();
private int countDown = 5;
private volatile double d = 0; // No optimization
public SimplePriorities(int priority) {
setPriority(priority);
start();
}
public String toString() {
return super.toString() + ": " + countDown;
}
public void run() {
while(true) {
// An expensive, interruptable operation:
for(int i = 1; i < 100000; i++)
d = d + (Math.PI + Math.E) / (double)i;
System.out.println(this);
if(--countDown == 0) return;
}
}
public static void main(String[] args) {
new SimplePriorities(Thread.MAX_PRIORITY);
for(int i = 0; i < 5; i++)
new SimplePriorities(Thread.MIN_PRIORITY);
monitor.expect(new String[] {
"Thread[Thread-1,10,main]: 5",
"Thread[Thread-1,10,main]: 4",
"Thread[Thread-1,10,main]: 3",
"Thread[Thread-1,10,main]: 2",
"Thread[Thread-1,10,main]: 1",
"Thread[Thread-2,1,main]: 5",
"Thread[Thread-2,1,main]: 4",
"Thread[Thread-2,1,main]: 3",
"Thread[Thread-2,1,main]: 2",
"Thread[Thread-2,1,main]: 1",
"Thread[Thread-3,1,main]: 5",
"Thread[Thread-4,1,main]: 5",
"Thread[Thread-5,1,main]: 5",
"Thread[Thread-6,1,main]: 5",
"Thread[Thread-3,1,main]: 4",
"Thread[Thread-4,1,main]: 4",
"Thread[Thread-5,1,main]: 4",
"Thread[Thread-6,1,main]: 4",
"Thread[Thread-3,1,main]: 3",
"Thread[Thread-4,1,main]: 3",
"Thread[Thread-5,1,main]: 3",
"Thread[Thread-6,1,main]: 3",
"Thread[Thread-3,1,main]: 2",
"Thread[Thread-4,1,main]: 2",
"Thread[Thread-5,1,main]: 2",
"Thread[Thread-6,1,main]: 2",
"Thread[Thread-4,1,main]: 1",
"Thread[Thread-3,1,main]: 1",
"Thread[Thread-6,1,main]: 1",
"Thread[Thread-5,1,main]: 1"
}, Test.IGNORE_ORDER + Test.WAIT);
}
} ///:~
In this version, toString( ) is overridden to use Thread.toString( ), which prints the thread name (which you can set yourself via the constructor; here it’s automatically generated as Thread-1, Thread-2, etc.), the priority level, and the “thread group” that the thread belongs to. Because the threads are self-identifying, there is no threadNumber in this example. The overridden toString( ) also shows the countdown value of the thread.
You can see that the priority level of thread 1 is at the highest level, and all the rest of the threads are at the lowest level.
Inside run( ), 100,000 repetitions of a rather expensive floating-point calculation have been added, involving double addition and division. The variable d has been made volatile to ensure that no optimization is performed. Without this calculation, you don’t see the effect of setting the priority levels (try it: comment out the for loop containing the double calculations). With the calculation, you see that thread 1 is given a higher preference by the thread scheduler (at least, this was the behavior on my Windows 2000 machine). Even though printing to the console is also an expensive behavior, you won’t see the priority levels that way, because console printing doesn’t get interrupted (otherwise, the console display would get garbled during threading), whereas the math calculation can be interrupted. The calculation takes long enough that the thread scheduling mechanism jumps in and changes threads, and pays attention to the priorities so that thread 1 gets preference.
You can also read the priority of an existing thread with getPriority( ) and change it at any time (not just in the constructor, as in SimplePriorities.java) with setPriority( ).
Although the JDK has 10 priority levels, this doesn’t map well to many operating systems. For example, Windows 2000 has 7 priority levels that are not fixed, so the mapping is indeterminate (although Sun’s Solaris has 231 levels). The only portable approach is to stick to MAX_PRIORITY, NORM_PRIORITY, and MIN_PRIORITY when you’re adjusting priority levels.
|
|