📄 tij0159.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0158.html">Prev</a> | <a href="tij0160.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Runnable
revisited
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Earlier
in this chapter, I suggested that you think carefully before making an applet
or main
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Frame</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as an implementation of <A NAME="Index2604"></A><A NAME="Index2605"></A><A NAME="Index2606"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If you take that approach, you can make only one of those threads in your
program. This limits your flexibility if you decide that you want to have more
than one thread of that type.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Of
course, if you must inherit from a class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>and</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you want to add threading behavior to the class,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is the correct solution. The final example in this chapter exploits this by
making a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Canvas</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class that paints different colors on itself. This application is set up to
take values from the command line to determine how big the grid of colors is
and how long to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
between color changes. By playing with these values you’ll discover some
interesting and possibly inexplicable features of threads:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: ColorBoxes.java</font>
<font color="#009900">// Using the Runnable interface</font>
<font color="#0000ff">import</font> java.awt.*;
<font color="#0000ff">import</font> java.awt.event.*;
<font color="#0000ff">class</font> CBox <font color="#0000ff">extends</font> Canvas <font color="#0000ff">implements</font> Runnable {
<font color="#0000ff">private</font> Thread t;
<font color="#0000ff">private</font> <font color="#0000ff">int</font> pause;
<font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">final</font> Color[] colors = {
Color.black, Color.blue, Color.cyan,
Color.darkGray, Color.gray, Color.green,
Color.lightGray, Color.magenta,
Color.orange, Color.pink, Color.red,
Color.white, Color.yellow
};
<font color="#0000ff">private</font> Color cColor = newColor();
<font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">final</font> Color newColor() {
<font color="#0000ff">return</font> colors[
(<font color="#0000ff">int</font>)(Math.random() * colors.length)
];
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> paint(Graphics g) {
g.setColor(cColor);
Dimension s = getSize();
g.fillRect(0, 0, s.width, s.height);
}
<font color="#0000ff">public</font> CBox(<font color="#0000ff">int</font> pause) {
<font color="#0000ff">this</font>.pause = pause;
t = <font color="#0000ff">new</font> Thread(<font color="#0000ff">this</font>);
t.start();
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
cColor = newColor();
repaint();
<font color="#0000ff">try</font> {
t.sleep(pause);
} <font color="#0000ff">catch</font>(InterruptedException e) {}
}
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> ColorBoxes <font color="#0000ff">extends</font> Frame {
<font color="#0000ff">public</font> ColorBoxes(<font color="#0000ff">int</font> pause, <font color="#0000ff">int</font> grid) {
setTitle("ColorBoxes");
setLayout(<font color="#0000ff">new</font> GridLayout(grid, grid));
<font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i < grid * grid; i++)
add(<font color="#0000ff">new</font> CBox(pause));
addWindowListener(<font color="#0000ff">new</font> WindowAdapter() {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">int</font> pause = 50;
<font color="#0000ff">int</font> grid = 8;
<font color="#0000ff">if</font>(args.length > 0)
pause = Integer.parseInt(args[0]);
<font color="#0000ff">if</font>(args.length > 1)
grid = Integer.parseInt(args[1]);
Frame f = <font color="#0000ff">new</font> ColorBoxes(pause, grid);
f.setSize(500, 400);
f.setVisible(<font color="#0000ff">true</font>);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ColorBoxes</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a typical application with a constructor that sets up the GUI. This
constructor takes an argument of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>int
grid
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to set up the <A NAME="Index2607"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>GridLayout</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so that it has
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>grid</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
cells in each dimension. Then it adds the appropriate number of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CBox</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects to fill the grid, passing the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>pause</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
value to each one. In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you can see how
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>pause</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>grid</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
have default values that can be changed if you pass in command-line arguments.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CBox
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">is
where all the work takes place. This is inherited from <A NAME="Index2608"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Canvas</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and it implements the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
interface so each
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Canvas</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can also be a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Remember that when you implement
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you don’t make a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, just a class that has a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. Thus, you must explicitly create a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object and hand the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Runnable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object to the constructor, then call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>start( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(this happens in the constructor). In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CBox</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
this thread is called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>t</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Notice
the array
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>colors</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is an enumeration of all the colors in class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Color</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is used in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>newColor( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to produce a randomly-selected color. The current cell color is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>cColor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>paint( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is quite simple – it just sets the color to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>cColor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and fills the entire canvas with that color.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you see the infinite loop that sets the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>cColor</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to a new random color and then calls
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>repaint( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to show it. Then the thread goes to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for the amount of time specified on the command line.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Precisely
because this design is flexible and threading is tied to each
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Canvas</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
element, you can experiment by making as many threads as you want. (In reality,
there is a restriction imposed by the number of threads your JVM can
comfortably handle.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
program also makes an interesting benchmark, since it can show dramatic speed
differences between one JVM implementation and another.
</FONT><a name="_Toc375545487"></a><a name="_Toc408018761"></a><P></DIV>
<A NAME="Heading508"></A><H3 ALIGN=LEFT>
Too
many threads
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">At
some point, you’ll find that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ColorBoxes</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
bogs down. On my machine, this occurred somewhere after a 10 x 10 grid. Why
does this happen? You’re naturally suspicious that the AWT might have
something to do with it, so here’s an example that tests that premise by
making fewer threads. The code is reorganized so that a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -