📄 chap14.htm
字号:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I8'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I9>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index1898"></A><A NAME="Index1899"></A><FONT FACE="Georgia">Threading
reduces computing efficiency somewhat, but the net improvement in program
design, resource balancing, and user convenience is often quite valuable. Of
course, if you have more than one CPU, then the operating system can dedicate
each CPU to a set of threads or even a single thread and the whole program can
run much faster. Multitasking and multithreading tend to be the most reasonable
ways to utilize multiprocessor systems.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I9'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I10>
</FONT><A NAME="_Toc375545473"></A><A NAME="_Toc481064847"></A><BR></P></DIV>
<A NAME="Heading482"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Inheriting from Thread</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The simplest way to create a thread is to
inherit from class <B>Thread</B>, which has all the wiring necessary to create
and run threads. The most important method for <B>Thread</B> is
<B>run( )</B>, which you must override to make the thread do your bidding.
Thus, <B>run( )</B> is the code that will be executed
“simultaneously” with the other threads in a program.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I10'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I11>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The following example creates any number
of threads that it keeps track of by assigning each thread a unique number,
generated with a <B>static</B> variable. The
<A NAME="Index1900"></A><B>Thread</B>’s <B>run( )</B> method is
overridden to count down each time it passes through its loop and to finish when
the count is zero (at the point when <B>run( )</B> returns, the thread is
terminated).</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c14:SimpleThread.java</font>
<font color=#009900>// Very simple Threading example.</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> SimpleThread <font color=#0000ff>extends</font> Thread {
<font color=#0000ff>private</font> <font color=#0000ff>int</font> countDown = 5;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>int</font> threadCount = 0;
<font color=#0000ff>private</font> <font color=#0000ff>int</font> threadNumber = ++threadCount;
<font color=#0000ff>public</font> SimpleThread() {
System.out.println(<font color=#004488>"Making "</font> + threadNumber);
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> run() {
<font color=#0000ff>while</font>(<font color=#0000ff>true</font>) {
System.out.println(<font color=#004488>"Thread "</font> +
threadNumber + <font color=#004488>"("</font> + countDown + <font color=#004488>")"</font>);
<font color=#0000ff>if</font>(--countDown == 0) <font color=#0000ff>return</font>;
}
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < 5; i++)
<font color=#0000ff>new</font> SimpleThread().start();
System.out.println(<font color=#004488>"All Threads Started"</font>);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A <B>run( )</B> method virtually
always has some kind of loop that continues until the thread is no longer
necessary, so you must establish the condition on which to break out of this
loop (or, in the case above, simply <B>return</B> from <B>run( )</B>).
Often, <B>run( )</B> is cast in the form of an infinite loop, which means
that, barring some external factor that causes <B>run( )</B> to terminate,
it will continue forever.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I11'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I12>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>main( ) </B>you can see a
number of threads being created and run. The <B>start( ) </B>method in the
<A NAME="Index1901"></A><B>Thread</B> class performs special initialization for
the thread and then calls <B>run( )</B>. So the steps are: the constructor
is called to build the object, then <B>start( )</B> configures the thread
and calls <B>run( )</B>. If you don’t call <B>start( )</B>
(which you can do in the constructor, if that’s appropriate) the thread
will never be started.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I12'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I13>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output for one run of this program
(it will be different from one run to another) is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Making 1
Making 2
Making 3
Making 4
Making 5
Thread 1(5)
Thread 1(4)
Thread 1(3)
Thread 1(2)
Thread 2(5)
Thread 2(4)
Thread 2(3)
Thread 2(2)
Thread 2(1)
Thread 1(1)
All Threads Started
Thread 3(5)
Thread 4(5)
Thread 4(4)
Thread 4(3)
Thread 4(2)
Thread 4(1)
Thread 5(5)
Thread 5(4)
Thread 5(3)
Thread 5(2)
Thread 5(1)
Thread 3(4)
Thread 3(3)
Thread 3(2)
Thread 3(1)</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You’ll notice that nowhere in this
example is <B>sleep( )</B> called, and yet the output indicates that each
thread gets a portion of the CPU’s time in which to execute. This shows
that <B>sleep( )</B>, while it relies on the existence of a thread in order
to execute, is not involved with either enabling or disabling threading.
It’s simply another method.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I13'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I14>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can also see that the
<A NAME="Index1902"></A>threads are not run in the order that they’re
created. In fact, the order that the CPU attends to an existing set of threads
is indeterminate, unless you go in and adjust the priorities using
<B>Thread</B>’s <B>setPriority( )</B> method.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I14'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I15>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When <B>main( )</B> creates the
<B>Thread</B> objects it isn’t capturing the references for any of them.
An ordinary object would be fair game for garbage collection, but not a
<B>Thread</B>. Each <B>Thread</B> “registers” itself so there is
actually a reference to it someplace and the garbage collector can’t clean
it up.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I15'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I16>
</FONT><A NAME="_Toc375545474"></A><A NAME="_Toc481064848"></A><BR></P></DIV>
<A NAME="Heading483"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Threading for a responsive interface<BR><A NAME="Index1903"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now it’s possible to solve the
problem in <B>Counter1.java </B>with a thread. The trick is to place the
subtask—that is, the loop that’s inside
<B>go( )</B>—inside the <B>run( )</B> method of a thread. When
the user presses the <B>start</B> button, the thread is started, but then the
<I>creation</I> of the thread completes, so even though the thread is running,
the main job of the program (watching for and responding to user-interface
events) can continue. Here’s the solution:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c14:Counter2.java</font>
<font color=#009900>// A responsive user interface with threads.</font>
<font color=#009900>// <applet code=Counter2 width=300 height=100></font>
<font color=#009900>// </applet></font>
<font color=#0000ff>import</font> javax.swing.*;
<font color=#0000ff>import</font> java.awt.*;
<font color=#0000ff>import</font> java.awt.event.*;
<font color=#0000ff>import</font> com.bruceeckel.swing.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Counter2 <font color=#0000ff>extends</font> JApplet {
<font color=#0000ff>private</font> <font color=#0000ff>class</font> SeparateSubTask <font color=#0000ff>extends</font> Thread {
<font color=#0000ff>private</font> <font color=#0000ff>int</font> count = 0;
<font color=#0000ff>private</font> <font color=#0000ff>boolean</font> runFlag = <font color=#0000ff>true</font>;
SeparateSubTask() { start(); }
<font color=#0000ff>void</font> invertFlag() { runFlag = !runFlag; }
<font color=#0000ff>public</font> <font color=#0000ff>void</font> run() {
<font color=#0000ff>while</font> (<font color=#0000ff>true</font>) {
<font color=#0000ff>try</font> {
sleep(100);
} <font color=#0000ff>catch</font>(InterruptedException e) {
System.err.println(<font color=#004488>"Interrupted"</font>);
}
<font color=#0000ff>if</font>(runFlag)
t.setText(Integer.toString(count++));
}
}
}
<font color=#0000ff>private</font> SeparateSubTask sp = <font color=#0000ff>null</font>;
<font color=#0000ff>private</font> JTextField t = <font color=#0000ff>new</font> JTextField(10);
<font color=#0000ff>private</font> JButton
start = <font color=#0000ff>new</font> JButton(<font color=#004488>"Start"</font>),
onOff = <font color=#0000ff>new</font> JButton(<font color=#004488>"Toggle"</font>);
<font color=#0000ff>class</font> StartL <font color=#0000ff>implements</font> ActionListener {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> actionPerformed(ActionEvent e) {
<font color=#0000ff>if</font>(sp == <font color=#0000ff>null</font>)
sp = <font color=#0000ff>new</font> SeparateSubTask();
}
}
<font color=#0000ff>class</font> OnOffL <font color=#0000ff>implements</font> ActionListener {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> actionPerformed(ActionEvent e) {
<font color=#0000ff>if</font>(sp != <font color=#0000ff>null</font>)
sp.invertFlag();
}
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> init() {
Container cp = getContentPane();
cp.setLayout(<font color=#0000ff>new</font> FlowLayout());
cp.add(t);
start.addActionListener(<font color=#0000ff>new</font> StartL());
cp.add(start);
onOff.addActionListener(<font color=#0000ff>new</font> OnOffL());
cp.add(onOff);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Console.run(<font color=#0000ff>new</font> Counter2 (), 300, 100);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>Counter2</B> is a straightforward
program, whose only job is to set up and maintain the user interface. But now,
when the user presses the <B>start</B> button, the event-handling code does not
call a method. Instead a thread of class <B>SeparateSubTask</B> is created, and
then the <B>Counter2</B> event loop continues.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER14_I16'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER14_I17>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The class <B>SeparateSubTask</B> is a
simple extension of <B>Thread</B> with a constructor that runs the thread by
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -