Priorities
Priorities
The priority of a thread tells the scheduler
how important this thread is. If there are a number of threads blocked and
waiting to be run, the scheduler will run the one with the highest priority
first. However, this doesn’t mean that threads with lower priority
don’t get run (that is, you can’t get deadlocked because of
priorities). Lower priority threads just tend to run less
often.
Although priorities are interesting to know about and
to play with, in practice you almost never need to set priorities yourself. So
feel free to skip the rest of this section if priorities aren’t
interesting to you.
Reading and setting priorities
You can read the priority of a thread with
getPriority( ) and change it with setPriority( ). The
form of the prior “counter” examples can be used to show the effect
of changing the priorities. In this applet you’ll see that the counters
slow down as the associated threads have their priorities
lowered:
//:
c14:Counter5.java
//
Adjusting the priorities of threads.
//
<applet code=Counter5 width=450 height=600>
//
</applet>
import
javax.swing.*;
import
java.awt.*;
import
java.awt.event.*;
import
com.bruceeckel.swing.*;
class
Ticker2
extends
Thread {
private
JButton
b =
new
JButton("Toggle"),
incPriority =
new
JButton("up"),
decPriority =
new
JButton("down");
private
JTextField
t =
new
JTextField(10),
pr =
new
JTextField(3); // Display
priority
private
int
count = 0;
private
boolean
runFlag =
true;
public
Ticker2(Container c) {
b.addActionListener(new
ToggleL());
incPriority.addActionListener(new
UpL());
decPriority.addActionListener(new
DownL());
JPanel p =
new
JPanel();
p.add(t);
p.add(pr);
p.add(b);
p.add(incPriority);
p.add(decPriority);
c.add(p);
}
class
ToggleL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
runFlag = !runFlag;
}
}
class
UpL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
int
newPriority = getPriority() + 1;
if(newPriority
> Thread.MAX_PRIORITY)
newPriority = Thread.MAX_PRIORITY;
setPriority(newPriority);
}
}
class
DownL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
int
newPriority = getPriority() - 1;
if(newPriority
< Thread.MIN_PRIORITY)
newPriority = Thread.MIN_PRIORITY;
setPriority(newPriority);
}
}
public
void
run() {
while
(true)
{
if(runFlag)
{
t.setText(Integer.toString(count++));
pr.setText(
Integer.toString(getPriority()));
}
yield();
}
}
}
public
class
Counter5
extends
JApplet {
private
JButton
start =
new
JButton("Start"),
upMax =
new
JButton("Inc Max
Priority"),
downMax =
new
JButton("Dec Max
Priority");
private
boolean
started =
false;
private
static
final
int
SIZE = 10;
private
Ticker2[] s =
new
Ticker2[SIZE];
private
JTextField mp =
new
JTextField(3);
public
void
init() {
Container cp = getContentPane();
cp.setLayout(new
FlowLayout());
for(int
i = 0; i < s.length; i++)
s[i] =
new
Ticker2(cp);
cp.add(new
JLabel(
"MAX_PRIORITY =
" + Thread.MAX_PRIORITY));
cp.add(new
JLabel("MIN_PRIORITY =
"
+ Thread.MIN_PRIORITY));
cp.add(new
JLabel("Group Max Priority =
"));
cp.add(mp);
cp.add(start);
cp.add(upMax);
cp.add(downMax);
start.addActionListener(new
StartL());
upMax.addActionListener(new
UpMaxL());
downMax.addActionListener(new
DownMaxL());
showMaxPriority();
// Recursively display parent
thread groups:
ThreadGroup parent =
s[0].getThreadGroup().getParent();
while(parent
!=
null)
{
cp.add(new
Label(
"Parent threadgroup max priority =
"
+ parent.getMaxPriority()));
parent = parent.getParent();
}
}
public
void
showMaxPriority() {
mp.setText(Integer.toString(
s[0].getThreadGroup().getMaxPriority()));
}
class
StartL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
if(!started)
{
started =
true;
for(int
i = 0; i < s.length; i++)
s[i].start();
}
}
}
class
UpMaxL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
int
maxp =
s[0].getThreadGroup().getMaxPriority();
if(++maxp
> Thread.MAX_PRIORITY)
maxp = Thread.MAX_PRIORITY;
s[0].getThreadGroup().setMaxPriority(maxp);
showMaxPriority();
}
}
class
DownMaxL
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
int
maxp =
s[0].getThreadGroup().getMaxPriority();
if(--maxp
< Thread.MIN_PRIORITY)
maxp = Thread.MIN_PRIORITY;
s[0].getThreadGroup().setMaxPriority(maxp);
showMaxPriority();
}
}
public
static
void
main(String[] args) {
Console.run(new
Counter5(), 450, 600);
}
}
///:~
Ticker2 follows the form established earlier in
this chapter, but there’s an extra JTextField for displaying the
priority of the thread and two more buttons for incrementing and decrementing
the priority.
Also notice the use of yield( ), which
voluntarily hands control back to the scheduler. Without this the multithreading
mechanism still works, but you’ll notice it runs slowly (try removing the
call to yield( ) to see this). You could also call
sleep( ), but then the rate of counting would be controlled by the
sleep( ) duration instead of the priority.
The init( ) in Counter5 creates an
array of ten Ticker2s; their buttons and fields are placed on the form by
the Ticker2 constructor. Counter5 adds buttons to start everything
up as well as increment and decrement the maximum priority of the thread group.
In addition, there are labels that display the maximum and minimum priorities
possible for a thread and a JTextField to show the thread group’s
maximum priority. (The next section will describe thread groups.) Finally, the
priorities of the parent thread groups are also displayed as labels.
When you press an “up” or
“down” button, that Ticker2’s priority is fetched and
incremented or decremented accordingly.
When you run this program, you’ll notice several
things. First of all, the thread group’s default priority is five. Even if
you decrement the maximum priority below five before starting the threads (or
before creating the threads, which requires a code change), each thread will
have a default priority of five.
The simple test is to take one counter and decrement
its priority to one, and observe that it counts much slower. But now try to
increment it again. You can get it back up to the thread group’s priority,
but no higher. Now decrement the thread group’s priority a couple of
times. The thread priorities are unchanged, but if you try to modify them either
up or down you’ll see that they’ll automatically pop to the priority
of the thread group. Also, new threads will still be given a default priority,
even if that’s higher than the group priority. (Thus the group priority is
not a way to prevent new threads from having higher priorities than existing
ones.)
Finally, try to increment the group maximum priority.
It can’t be done. You can only reduce thread group maximum priorities, not
increase them
|