📄 ch8.htm
字号:
a greater whole. Each thread can be seen as existing as part ofa single, greater unit. For example, when the process dies, sodo all its threads.<H2><A NAME="CreatingaThreadwiththeThreadClass"><FONT SIZE=5 COLOR=#FF0000>Creatinga Thread with the Thread Class</FONT></A></H2><P>Java offers a variety of tools for writing multithreaded programs.The most useful is the Thread class, which, as its name suggests,is used for creating a class that runs as a thread. You need todeclare a subclass of Thread if you want to create a functionalthread. After the subclass is created, you need to override Thread's<TT>run()</TT> method. This methodis the key to making the Thread class perform as a thread; itdefines your class's thread of execution. After the <TT>run()</TT>method is established and your class is instantiated, you canbegin the thread with the <TT>start()</TT>method.<P>A simple example shows how easy it is to create a thread in Java.Figure 8.1 shows an applet with lines drawn randomly throughoutits workspace. These lines are drawn by a thread using the codein Listing 8.1. The class LineThread is a subclass of Thread thatloops indefinitely, randomly drawing lines on an applet. The appletis provided to LineThread through its constructor. Although theLineThread class has a custom constructor, Thread classes oftendo not have special constructors.<P><A HREF="f8-1.gif" ><B>Figure 8.1 : </B><I>An applet with lines drawn by a thread </I></A><HR><BLOCKQUOTE><B>Listing 8.1. The source code for applet with lines drawn bya thread.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>import java.awt.*;<BR>import java.lang.*;<BR>import java.applet.Applet;<BR><BR>// This is an applet that creates a Thread that<BR>// randomly draws lines on its workspace...<BR>public class LineApplet extends Applet {<BR> Thread t;<BR> // Set the size of the applet, create the thread,<BR> // and start it...<BR> public void init() {<BR> resize(300,300);<BR> t = new LineThread(this);<BR> t.start();<BR> }<BR><BR> // Click the mouse to kill the thread...<BR> public boolean mouseDown(Event ev, int x1, intx2) {<BR><BR> if (t != null) {<BR> t.stop();<BR> t = null;<BR> }<BR> return true;<BR> };<BR>}<BR><BR>// Thread that randomly draws lines all over a component...<BR>class LineThread extends Thread {<BR> Applet a; // Thread needs to knowthe applet...<BR> // Constructor simply stores the applet to paint...<BR> public LineThread(Applet a) {<BR> this.a = a;<BR> }<BR><BR> // Run the thread. Lines everywhere!<BR> public void run() {<BR> // Get dimension data aboutthe applet...<BR> double width = (double) a.size().width;<BR> double height = (double)a.size().height;<BR> // Loop and draw lines forever...<BR> while (true) {<BR> Graphicsg = a.getGraphics();<BR> g.drawLine((int)(width* Math.random()),<BR> (int)(height* Math.random()),<BR> (int)(width* Math.random()),<BR> (int)(height* Math.random()) );<BR> }<BR> }<BR>}</TT></BLOCKQUOTE><HR><P>The <TT>run()</TT> method of LineThreadprovides the applet's threaded activity. After getting the applet'sdimensions, the thread enters an indefinite <TT>while</TT>loop, randomly drawing lines on each iteration. (The Componentclass's <TT>getGraphics()</TT> methodis a way of getting a Graphics object to draw on a component outsidethe <TT>paint()</TT> method.) Thethread will run until the applet is terminated or until the threadis explicitly stopped.<P>After setting its own size and constructing a LineThread object,the Applet class, LineApplet, begins the line drawing by callingthe <TT>start()</TT> method. This<TT>start()</TT> method call beginsthe thread and invokes the <TT>run()</TT>method of the LineThread class. The thread will not run untilthe <TT>start()</TT> method is applied.<P>The <TT>stop()</TT> method terminatesa thread. In a general sense, <TT>stop()</TT>causes a thread to abruptly leave its <TT>run()</TT>method and, therefore, end its threaded activity. In this example,a mouse click on the applet causes the thread (and hence the linedrawing) to stop.<H3><A NAME="EnhancingYourFirstMultithreadedApple">Enhancing YourFirst Multithreaded Applet</A></H3><P>A couple of things can be done to this applet to further illustratethe Thread class. Listing 8.2 gives the source code for the enhancedversion of the applet. The threaded class, LineThread, was modifiedto delay a little between the line drawings by using the <TT>sleep()</TT>method, which causes the thread to "sleep" for a specificnumber of milliseconds; in this case, the delay is for a tenthof a second. Note how the <TT>sleep()</TT>method requires catching InterruptedException objects. This ismeant for situations in which a thread has been interrupted byanother thread. However, this capability doesn't seem to be activein the current version of the JDK. Consequently, you will seenull handlers for InterruptedException objects throughout thisbook. Because it is annoying to have to have an exception handlerevery time you call <TT>sleep()</TT>,you might want to encapsulate <TT>sleep()</TT>and the exception handling in your own method. This techniqueappears in the code used elsewhere in this book.<HR><BLOCKQUOTE><B>Listing 8.2. Enhanced version of the line-drawing applet.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>import java.awt.*;<BR>import java.lang.*;<BR>import java.applet.Applet;<BR><BR>// This is an applet that creates a Thread that<BR>// randomly draws lines on its workspace...<BR>public class LineApplet extends Applet {<BR> Thread t;<BR> boolean running = false;<BR> // Set the size of the applet, create the thread<BR> // and start it...<BR> public void init() {<BR> resize(300,300);<BR> t = new LineThread(this);<BR> t.start();<BR> running = true;<BR> }<BR><BR> // Click the mouse down to kill the thread...<BR> public boolean mouseDown(Event ev, int x1, intx2) {<BR> // If the thread is active, suspend thethread<BR> // and remove the lines...<BR> if (running) {<BR> running = false;<BR> t.suspend();<BR> repaint(); // Removes thelines...<BR> }<BR> // If thread is suspended, then reactivateit...<BR> else {<BR> running = true;<BR> t.resume();<BR> }<BR> return true;<BR> };<BR><BR> // Destroy the thread when the applet shutsdown...<BR> public void destroy() {<BR> // Stop the thread and wait for it todie...<BR> t.stop();<BR> try {<BR> t.join();<BR> }<BR> catch (InterruptedException e) { }<BR> }<BR>}<BR><BR>// Thread that randomly draws lines all over a component...<BR>class LineThread extends Thread {<BR> Applet a; // Thread needs to knowthe applet...<BR> // Constructor simply stores the applet to paint...<BR> public LineThread(Applet a) {<BR> this.a = a;<BR> }<BR><BR> // Run the thread. Lines everywhere!<BR> public void run() {<BR> // Get dimension data about the applet...<BR> double width = (double) a.size().width;<BR> double height = (double)a.size().height;<BR> // Loop and draw lines forever...<BR> while (true) {<BR> Graphics g = a.getGraphics();<BR> // Randomly select a color...<BR> Color c = new Color((int)(255.0 * Math.random()),<BR> (int)(255.0 * Math.random()),<BR> (int)(255.0 * Math.random()));<BR> g.setColor(c);<BR> g.drawLine((int)(width * Math.random()),<BR> (int)(height * Math.random()),<BR> (int)(width * Math.random()),<BR> (int)(height * Math.random()));<BR> // Sleep some...<BR> try {<BR> sleep(100);<BR> }<BR> catch (InterruptedException e) {}<BR> }<BR> }<BR>}</TT></BLOCKQUOTE><HR><P>A visual enhancement also was made to LineThread. It randomlycreates a new Color object and uses it (with the Graphics class<TT>setColor()</TT> method) in eachiteration. Figure 8.2 shows the enhancement.<P><A HREF="f8-2.gif" ><B>Figure 8.2 : </B><I>Second version of the linedrawing applet </I></A><P>Most of the changes occur in the Applet class LineApplet. Themethod that traps the mouse clicks, <TT>mouseDown()</TT>,is changed so it no longer stops the thread. It now toggles betweenpausing and resuming the thread's execution. The <TT>suspend()</TT>method suspends a thread's execution; when a thread is suspended,it will not continue its stream of execution until the complementary<TT>resume()</TT> method is invoked.In this example, suspending a thread is accompanied by clearingout the applet's drawing area through the <TT>repaint()</TT>method. (This clearing occurs because the applet does not overridethe <TT>paint()</TT> method.) The<TT>running</TT> variable is usedto keep track of whether the thread is suspended; unfortunately,there is no method in the Thread class for determining this.<P>The last bit of code occurs in the newly added <TT>destroy()</TT>method, which is called when the applet shuts down. In this call,the <TT>stop()</TT> method terminatesthe thread. It is accompanied by a <TT>join()</TT>call, which forces the calling thread to wait until the victimthread is really "dead." This is important because stoppinga thread does not cause an immediate (in the strict sense of theword) termination of the thread. There may be some delay due totime-slicing or some other reason. It is often dangerous not towait for a thread to die. In some cases, the thread may run evenafter some of the objects it uses (like the applet) are no longervalid. This will cause an exception. Furthermore, an applet thathas been stopped without waiting for its constituent threads toterminate could cause the applet to unexpectedly "hang."Consequently, it's good practice to follow <TT>stop()</TT>calls by a complementary call to <TT>join()</TT>to prevent this from happening. It should be noted that the Threadclass has two additional versions of <TT>join()</TT>that take time-out flags. Use these if your applet has some severetime constraints and you cannot afford to wait indefinitely fora thread to end. The time-out values (like most time-outs in Java)are in milliseconds with an optional nanosecond precision value.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -