📄 ch31.htm
字号:
String displayStr; Font font; public void start() { font = new Font("TimesRoman", Font.PLAIN, 72); setFont(font); count = 0; displayStr = ""; thread = new Thread(this); thread.start(); } public void stop() { thread.stop(); } public void run() { while (count < 1000) { ++count; displayStr = String.valueOf(count); repaint(); try { thread.sleep(100); } catch (InterruptedException e) { } } } public void paint(Graphics g) { g.drawString(displayStr, 50, 130); }}</PRE></BLOCKQUOTE><HR><P><IMG ALIGN=RIGHT SRC="pseudo.gif" HEIGHT=94 WIDTH=94 BORDER=1><BLOCKQUOTE>Tell Java that the applet uses the classes in the <TT>awt</TT>package.<BR>Tell Java that the applet uses the classes in the <TT>applet</TT>package.<BR>Derive <TT>ThreadApplet</TT> from <TT>Applet</TT> and implement<TT>Runnable</TT>.<BR> Declare the class's data fields, including a <TT>Thread </TT>object.<BR> Override the <TT>start()</TT> method.<BR> Create and set the applet's display font.<BR> Initialize data fields.<BR> Create and start the thread.<BR> Override the <TT>stop()</TT> method.<BR> Stop the thread.<BR> Implement the <TT>run()</TT> method<BR> Loop one thousand times.<BR> Increment the counter.<BR> Create the display string from the counter.<BR> Tell Java to repaint the applet.<BR> Suspend the thread for one hundred milliseconds.<BR> Override the <TT>paint()</TT> method.<BR> Draw the display string.</BLOCKQUOTE><P>There are a couple of interesting things in ThreadApplet of whichyou should be aware. First, notice that in <TT>run()</TT>, thethread loops one thousand times, after which the <TT>while</TT>loop ends. When the <TT>while</TT> loop ends, so does the <TT>run()</TT>method. This means that when you run ThreadApplet, if you letit count all the way to one thousand, the thread ends on its own.However, what if you switch to a different Web page before ThreadApplethas counted all the way to one thousand? Then, Java calls theapplet's <TT>stop()</TT> method, which ends the thread by callingthe thread's <TT>stop()</TT> method.<P>The next point of interest is what's going on inside <TT>run()</TT>.At the beginning of the loop, the program increments the counter,converts the counter's value to a string, and then repaints theapplet so that the new count value appears in the window. Thatcode should be as clear as glass to you by now. But what's allthat malarkey after the call to <TT>repaint()</TT>? That's wherethe thread not only times the animation, but also relinquishesthe computer so that other threads get a chance to run. Simply,the call to the thread's <TT>sleep()</TT> method suspends thethread for the number of milliseconds given as its single argument.In this case, the sleep time is 100 milliseconds, or one tenthof a second. If you want the animation to run faster, change the100 to a smaller value. To count slower, change the 100 to a largervalue.<P><CENTER><TABLE BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>CAUTION</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>It's important that your threads not dominate the computer's processor for longer than necessary. This is because other threads and processes are almost certainly in competition for the processor at the same time. If your thread will be running for a while, you should call the <TT>sleep()</TT> or <TT>yield() </TT>methods in order to give other processes a chance to run. This is more important on some systems than on others, but since you can't know for sure which system your applet will be running on, be a considerate thread programmer.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>Notice that the call to <TT>sleep()</TT> is enclosed in a <TT>try</TT>block and followed by a <TT>catch</TT> block that's watching for<TT>InterruptedException</TT> exceptions. You have to catch thisexception because the <TT>sleep()</TT> method throws it. If youfail to catch the exception, your program will not compile.<H2><A NAME="DerivingaClassfromIThreadI"><FONT SIZE=5 COLOR=#Ff0000>Deriving a Class from <I>Thread</I></FONT></A></H2><P>The second way to create a thread is to derive a new class from<TT>Thread</TT>. Then, in your applet's class, you create andstart a thread object of your thread class. This leaves you withtwo processes going simultaneously, the applet and the threadobject created in the class. By giving the thread class accessto data and methods in the applet, the thread can easily communicatewith the applet in order to perform whatever tasks it was writtenfor.<H3><A NAME="ExampleCreatingaThreadClass">Example: Creating a Thread Class</A></H3><P>Suppose that you want to write the same sort of applet as thatshown in Listing 31.3, but now you want a separate thread to controlthe counting process. Listing 31.4 shows how you might write thenew class for the thread. (Don't try to compile this code yet.You'll use it in the next example in this chapter.)<HR><BLOCKQUOTE><B>Listing 31.4 MyThread.java: A Class Derived from</B><I>Thread.<BR></I></BLOCKQUOTE><BLOCKQUOTE><PRE>public class MyThread extends Thread{ ThreadApplet2 applet; int count; MyThread(ThreadApplet2 applet) { this.applet = applet; } public void run() { count = 0; while (count < 1000) { ++count; applet.displayStr = String.valueOf(count); applet.repaint(); try { sleep(100); } catch (InterruptedException e) { } } }}</PRE></BLOCKQUOTE><HR><P><IMG ALIGN=RIGHT SRC="pseudo.gif" HEIGHT=94 WIDTH=94 BORDER=1><BLOCKQUOTE>Derive the <TT>MyThread</TT> class from <TT>Thread</TT>.<BR> Declare the class's data fields, including a <TT>Thread</TT>object.<BR> Declare the class's constructor.<BR> Store the constructor's single parameter.<BR> Override the <TT>run()</TT> method<BR> Loop one thousand times.<BR> Increment the counter.<BR> Create the display string from the counter.<BR> Tell Java to repaint the applet.<BR> Suspend the thread for one hundred milliseconds.</BLOCKQUOTE><P>The first thing to notice in this thread class is that its constructortakes as a single argument a reference to a <TT>ThreadApplet2</TT>object, which is the applet from which you'll be running thisthread. The thread needs this reference so that it can communicatewith the applet.<P>Next, look at <TT>run()</TT>. The thread still counts from zeroto one thousand, but now it accesses the applet object in orderto create the display string and repaint the applet. In the originalversion of the program, the thread was directly associated withthe class, rather than a completely separate process.<P>Now that you have a new thread class, you'll want to call it upfor active duty. You'll do that in the next example.<H3><A NAME="ExampleUsingaSeparateThreadinanApplet">Example: Using a Separate Thread in an Applet</A></H3><P>You'll now put that new thread class to work. To do this, youmust have an applet that creates an object from the new threadclass and calls that object's <TT>start()</TT> method to get thethread running. Listing 31.5 shows just such an applet, calledThreadApplet2. When you run the applet under Appletviewer, you'llsee the same display that was created in the original versionof the applet (ThreadApplet), but now the counting animation isbeing controlled by a separate thread class.<P><CENTER><TABLE BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>NOTE</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>To compile Listing 31.5, make sure you have both the MyThread.java and ThreadApplet2.java files in your CLASSES folder. Java will then compile both files when you compile ThreadApplet2.java.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><HR><BLOCKQUOTE><B>Listing 31.5 ThreadApplet2.JAVA: An Applet ThatCreates a Separate Thread.<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>import java.awt.*;import java.applet.*;import MyThread;public class ThreadApplet2 extends Applet{ MyThread thread; String displayStr; Font font; public void start() { font = new Font("TimesRoman", Font.PLAIN, 72); setFont(font); displayStr = ""; thread = new MyThread(this); thread.start(); } public void stop() { thread.stop(); } public void paint(Graphics g) { g.drawString(displayStr, 50, 150); }}</PRE></BLOCKQUOTE><HR><P><IMG ALIGN=RIGHT SRC="pseudo.gif" HEIGHT=94 WIDTH=94 BORDER=1><BLOCKQUOTE>Tell Java that the applet uses the classes in the <TT>awt</TT>package.<BR>Tell Java that the applet uses the classes in the <TT>applet</TT>package.<BR>Tell Java that the applet uses the <TT>MyThread</TT> class.<BR>Derive the <TT>ThreadApplet2</TT> class from <TT>Applet.<BR></TT> Declare the class's data fields, including a <TT>MyThread</TT>object.<BR> Override the <TT>start()</TT> method<BR> Create and set the applet's font.<BR> Initialize the display string.<BR> Create and start the thread.<BR> Override the <TT>stop()</TT> method.<BR> Stop the thread.<BR> Override the <TT>paint() </TT>method.<BR> Draw the applet's display string, which is the currentcount.</BLOCKQUOTE><H2><A NAME="SynchronizingMultipleThreads"><FONT SIZE=5 COLOR=#Ff0000>Synchronizing Multiple Threads</FONT></A></H2><P>There may be times when you have several threads going, each competingfor the same resources. This type of resource competition canbe deadly for threads. For example, what if one thread tries toread from a string while another thread is still writing to thatstring? Depending on the situation, you'll get strange results.You can avoid these problems by telling Java where synchronizationproblems may occur so that Java can keep an eye out for unhealthythread competition.<P>To put Java on guard, you use the <TT>synchronized</TT> keywordwhen you define a method (or even a code block). When you marka method as synchronized, Java creates a monitor object for theclass. The first time a thread calls the synchronized method,Java gives the monitor object to that thread. As long as the threadholds the monitor object, no other thread can enter the synchronizedsection of code. You can think of the monitor object as a key.Unless a thread is holding the key, it can't unlock the door tothe synchronized method.<H3><A NAME="ExampleUsingaSynchronizedMethod">Example: Using a Synchronized Method</A></H3><P>Using synchronized methods makes sense only when more than onethread is vying for an applet's resources. For that reason, todemonstrate thread synchronization, you need to create two threads.Listing 31.6 is a thread class, called MyThread2, that can counteither forward or backward, depending upon the values you giveto the class's constructor. By creating two thread objects fromthis class, you can experiment with thread synchronization.<P><CENTER><TABLE BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>NOTE</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>To compile Listings 31.6 and 31.7, make sure you have both the MyThread2.java and ThreadApplet3.java files in your CLASSES folder. Java will then compile both files when you compile ThreadApplet3.java.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><HR><BLOCKQUOTE><B>Listing 31.6 MyThread2.java: A Double-Duty Thread.<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>public class MyThread2 extends Thread{ ThreadApplet3 applet; boolean forward; int count; int increment; int end; int position; MyThread2(ThreadApplet3 applet, boolean forward) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -