Understanding Thread Priority
As mentioned
When a thread is created, it inherits its priority from the thread that created it. You also can modify a thread's priority at any time after its creation by using the
setPriority
method. Thread priorities are integers
Then the second thread is given a chance to run, and so on, until the interpreter exits.
The Java runtime environment's thread-scheduling algorithm is also
preemptive
. If at any time a thread with a priority higher than that of all other Runnable threads becomes Runnable, the runtime system chooses the new higher-priority thread for execution. This new thread is said to
Rule of Thumb
At any given time, the highest-priority thread is running. However, this is not
The 400,000-Micron Thread Race
Figure 83. A snapshot of RaceApplet with runners of different priorities.
Try This Go to the online version of this section and run the applet. Note that this applet may not work as intended in browsers that have security restrictions regarding setting a thread's priority. If this is true for your browser, try running this applet in an applet viewer instead.
public int tick = 1;
public void run() {
while (tick < 400000) {
tick++;
}
}
This applet has a third thread, which handles the drawing. The drawing thread's
run
method
This is not a fair race, because one runner has a higher priority than the other. Each time the drawing thread yields the CPU by going to sleep for 10 milliseconds, the scheduler chooses the highest-priority Runnable thread to run; in this case, it's always runner 3. Figure 84 is another snapshot of the applet, one that implements a fair race, in which both runners have the same priority and an equal chance of being chosen to run. Figure 84. A snapshot of RaceApplet with runners of the same priority.
Try This Go to the online version of this section and run the applet. [1]
In this race, each time the drawing thread yields the CPU by going to sleep, there are two Runnable threads of equal priority -the runners -waiting for the CPU. The scheduler must choose one of the threads to run. In this case, the scheduler arbitrarily chooses one. Selfish Threads
The
Runner
class used in the previous races implements "
public int tick = 1;
public void run() {
while (tick < 400000) {
tick++;
}
}
The while loop in the run method is in a tight loop. Once the scheduler chooses a thread with this thread body for execution, the thread never voluntarily relinquishes control of the CPU; it just continues to run until the while loop terminates naturally or until the thread is preempted by a higher-priority thread. This thread is called a selfish thread .
In some cases, having selfish threads doesn't cause any problems, because a higher-priority thread preempts the selfish one, just as the drawing thread in
RaceApplet
preempts the selfish runners. However, in other cases, threads with CPU-greedy
run
Time Slicing
public void run() {
while (tick < 400000) {
tick++;
if ((tick % 50000) == 0) {
System.out.println("Thread #" + num + ", tick = " + tick);
}
}
}
This
run
method contains a tight loop that
When running this program on a time-sliced system, you will see messages from both threads intermingled, like this: Thread #1, tick = 50000 Thread #0, tick = 50000 Thread #0, tick = 100000 Thread #1, tick = 100000 Thread #1, tick = 150000 Thread #1, tick = 200000 Thread #0, tick = 150000 Thread #0, tick = 200000 Thread #1, tick = 250000 Thread #0, tick = 250000 Thread #0, tick = 300000 Thread #1, tick = 300000 Thread #1, tick = 350000 Thread #0, tick = 350000 Thread #0, tick = 400000 Thread #1, tick = 400000
This output is produced because a time-sliced system divides the CPU into time slots and gives each equal-and-highest priority thread a time slot in which to run. The time-sliced system iterates through the equal-and-highest priority threads, allowing each one a bit of time to run, until one or more finishes or until a higher-priority thread preempts them. Note that time slicing makes no
When running this program on a system that is not time sliced, you will see messages from one thread finish printing before the other thread ever gets a chance to print one message. The output will look like this: Thread #0, tick = 50000 Thread #0, tick = 100000 Thread #0, tick = 150000 Thread #0, tick = 200000 Thread #0, tick = 250000 Thread #0, tick = 300000 Thread #0, tick = 350000 Thread #0, tick = 400000 Thread #1, tick = 50000 Thread #1, tick = 100000 Thread #1, tick = 150000 Thread #1, tick = 200000 Thread #1, tick = 250000 Thread #1, tick = 300000 Thread #1, tick = 350000 Thread #1, tick = 400000 The reason is that a system that is not time sliced chooses one of the equal-and-highest priority threads to run and allows that thread to run until it relinquishes the CPU (by sleeping, yielding, or finishing its job) or until a higher-priority preempts it.
Purity Tip The Java platform does not implement (and therefore does not guarantee) time slicing. However, some platforms do support time slicing. Your programs should not rely on time slicing, as it may produce different results on different systems.
As you can imagine, writing CPU-
A thread can voluntarily yield the CPU by calling the yield method. The yield method gives other threads of the same priority a chance to run. If no equal-priority threads are Runnable, the yield is ignored. Summarizing Thread Priority
|