📄 ch8.htm
字号:
}<BR> }<BR><BR> // Pop the top item off the stack...<BR> public Integer pop() throws StackEmptyException{<BR> Integer I;<BR> synchronized(this) {<BR> // Throw exception if stackis empty...<BR> if (top < 0)<BR> thrownew StackEmptyException();<BR> // Otherwise, return the topitem and decrement the top...<BR> I = s[top];<BR> s[top] = null;<BR> -top;<BR> }<BR> return I;<BR> }<BR><BR> // List the contents of the stack...<BR> public void list() {<BR> synchronized(this) {<BR> for (int i = 0; i <= top;++i)<BR> System.out.println(i+ ": " + s[i]);<BR> }<BR> }<BR>}</TT></BLOCKQUOTE><HR><P>The code blocks in Listing 8.6 could just have easily been synchronizedwith the stack Integer array <TT>s</TT>.The results would be the same. However, you cannot synchronizewith the integer variable <TT>top</TT>.The synchronized modifier works only with objects and classes;variables, such as integers, are not proper synchronization types.<H3><A NAME="NotifyandWait">Notify and Wait</A></H3><P>Suppose that you wanted to change the TestStack class to be blocking.That is, if you are invoking the <TT>pop()</TT>method and there is nothing on the stack, then you should waituntil some other thread adds an element to the stack. However,because the <TT>pop()</TT> methodis synchronized, you cannot wait inside that method without lockingout the thread that is going to add the element you need! Whatyou would like to do is wait inside the <TT>pop()</TT>method but relinquish the TestStack object monitor so that otherthreads can use the stack.<P>Fortunately, the designers of Java come to your rescue again!The base Object class has several methods built into it for thissituation. Because these methods are part of the base class, theyare available for every class you create. The <TT>wait()</TT>method provides the behavior you need for the <TT>pop()</TT>problem just discussed. When it is called, the <TT>wait()</TT>method releases the Object's monitor and simply waits until itis notified. Notification occurs when another thread calls thesame Object's <TT>notify()</TT> method.This causes the waiting thread to wake up and reacquire the monitor.If the thread finds what it needs, it can leave the method andrelease the lock; otherwise, it can call <TT>wait()</TT>again.<P>Listing 8.7 shows modified methods of the TestStack class thatimplement the blocking behavior just discussed. The <TT>pop()</TT>method no longer throws an exception if the stack is empty. Itnow waits until the <TT>push()</TT>method calls <TT>notify()</TT> toindicate that an item has been added to the stack. In this example,the <TT>wait()</TT> method will waitindefinitely for an item to be added to the stack. In the Queueclass developed in this chapter's project, you will see the useof alternate <TT>wait()</TT> methodsthat have time-outs associated with them.<HR><BLOCKQUOTE><B>Listing 8.7. The TestStack class with a blocking </B><TT><B><FONT SIZE=1 FACE="Courier">pop()</FONT></B></TT><B>method.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>// Push an item onto the stack...<BR> public synchronized void push(Integer item)throws StackFullException {<BR> // Throw exception if stackis full...<BR> if (top == s.length)<BR> thrownew StackFullException();<BR> // Otherwise increment thetop and add the item...<BR> ++top;<BR> s[top] = item;<BR> <B>notify</B>(); //Let pop know you got something...<BR> }<BR><BR> // Pop the top item off the stack...<BR> public synchronized Integer pop() {<BR> // Wait indefinitely if stackis empty...<BR> while (top < 0) {<BR> try {<BR> <B>wait</B>();<BR> }<BR> catch (InterruptedExceptione) { }<BR> } // end while<BR> // Otherwise, return the topitem and decrement the top...<BR> Integer I = s[top];<BR> s[top] = null;<BR> -top;<BR> return I;<BR> }</TT></BLOCKQUOTE><HR><P>Listing 8.8 shows the StackThread class that is modified to usethe blocking <TT>pop()</TT> method.The <TT>run()</TT> method is a lotsimpler than before because it no longer has to sleep betweeninvocations of <TT>pop()</TT>. Thisis done implicitly when it is waiting for the TestStack to change.<HR><BLOCKQUOTE><B>Listing 8.8. The StackThread class modified to use the blocking</B><TT><B><FONT SIZE=1 FACE="Courier">pop()</FONT></B></TT><B>method.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>// Thread that constantly reads the stackand prints out<BR>// the current top...<BR>class StackThread extends Thread {<BR> TestStack s;<BR> public StackThread(TestStack s) {<BR> this.s = s;<BR> }<BR> // Loop forever, looking at the top of the stack...<BR> public void run() {<BR> Integer Top;<BR> while (true) {<BR> // Printout top of stack, if stack isn't empty...<BR> // Waitindefinitely if the stack is empty...<BR> Top = s.pop();<BR> System.out.println("Thread:Read " + Top);<BR> }<BR> }<BR>}</TT></BLOCKQUOTE><HR><P>If more than one thread is waiting on an object, the <TT>notifyAll()</TT>method can be used to tell all waiting threads of the change inthe object's state. On the other hand, the <TT>notify()</TT>method will send a signal only to a single waiting thread. Itshould also be noted that the <TT>notify()</TT>and <TT>wait()</TT> methods can becalled only from within a synchronized method and from the threadthat currently owns the object's monitor. For example, if theStackApplet object tried to call the TestStack object's <TT>notify()</TT>method, an IllegalMonitorStateException would be thrown.<H2><A NAME="MoreAboutThreads"><FONT SIZE=5 COLOR=#FF0000>MoreAbout Threads</FONT></A></H2><P>Suppose you need one of your objects to sleep for a while, butthe object is not an instance of the Thread class. How can thisbe done? The Thread class has a static method, called <TT>currentThread()</TT>,that returns a reference to the Thread object currently beingexecuted. If the code is structured as in the following example,you can get the Thread reference you need:<BLOCKQUOTE><TT>public class MyClass { //Note it does not extend Thread<BR> public MyMethod() {<BR> // ...work for a while...<BR> // Now sleep for 2 seconds<BR> Thread.currentThread().sleep(2000);<BR> // ...back to work...<BR> }<BR>}</TT></BLOCKQUOTE><P>With the reference returned from <TT>currentThread()</TT>,you can execute the Thread methods that your class needs to perform.If you engage in serious Java programming, you will find the methodto be useful in a wide variety of situations.<P>Another feature of the Thread class is that threads can run atdifferent priority levels. Recall that threads generally operateby using time-slicing. Setting the priority of a thread lets youestablish how large a time-slice your thread will get in relationto other threads. For example, a high-priority thread will getlarger slices of time to process than a low-priority thread will.The Thread class supplies three public variables that can be usedto define a thread's priority:<UL><LI><TT>MIN_PRIORITY</TT> indicatesthe minimum priority value in which a thread can run. A threadset to this priority will receive little processing time. It isbest used for low-priority activities whose rate of completionisn't important. In this context, it is worth noting that theJava garbage collector runs at low priority (although it may notbe <TT>MIN_PRIORITY</TT>).<LI><TT>NORMAL_PRIORITY</TT> indicatesthe default value in which a thread runs. Most threads you createwill run at this priority.<LI><TT>MAX_PRIORITY</TT> indicatesthe maximum priority value in which a thread can run. A threadrunning at this priority will take most of the available CPU time.This should be used only for short CPU-intensive tasks that needto finish quickly.</UL><P>In general, these priorities are set at the values of <TT>1</TT>,<TT>5</TT>, and <TT>10</TT>,respectively. However, it is best not to code with this knowledgebecause these variable definitions exist to hide their underlyingvalues.<P>A thread's priority can be set with the <TT>setPriority()</TT>method. This method takes an integer priority value as its soleparameter. It throws an IllegalArgumentException if the prioritydoes not fall within the bounds of <TT>MIN_PRIORITY</TT>and <TT>MAX_PRIORITY</TT>, inclusively.For example, this code sets the priority of a thread to the minimumvalue:<BLOCKQUOTE><TT>// Create the thread...<BR>myThread t;<BR>t = new MyThread().<BR>// Set the priority to minimum<BR>try {<BR> t.setPriority(Thread.MIN_PRIORITY);<BR>}<BR>// This exception will not occur!<BR>catch (IllegalArgumentException e) {<BR> System.out.println(e.getMessage());<BR>}<BR>// Start the thread at the low priority...<BR>t.start();</TT></BLOCKQUOTE><P>The priority of a thread can be retrieved with the <TT>getPriority()</TT>method. Table 8.1 provides a summary of Thread class methods thatyou may find useful. Note that ThreadGroups and daemons will bediscussed next.<BR><P><B>Table 8.1. Summary of important methods of the Thread class.</B><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD WIDTH=175><TT><I>Method</FONT></I></TT></TD><TD WIDTH=415><I>Description</I></TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>currentThread()</TT></TD><TD WIDTH=415>Returns a reference to the currently executing Thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>getName()</TT></TD><TD WIDTH=415>Gets the name of the Thread. Assigned manually or automatically in the constructor.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>getPriority()</TT></TD><TD WIDTH=415>Returns the priority of a Thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>GetThreadGroup()</TT></TD><TD WIDTH=415>Returns the ThreadGroup of a thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>isAlive()</TT></TD><TD WIDTH=415>Returns whether the Thread is alive; that is, it has been started but not stopped.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>join()</TT></TD><TD WIDTH=415>Waits for a Thread to die.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>resume()</TT></TD><TD WIDTH=415>Resumes the running of a suspended Thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>run()</TT></TD><TD WIDTH=415>Establishes where the threaded activity occurs.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>setDaemon()</TT></TD><TD WIDTH=415>Establishes the Thread as a daemon or user thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>setPriority()</TT></TD><TD WIDTH=415>Sets the priority of a Thread.</TD></TR><TR VALIGN=TOP><TD WIDTH=175><TT>sleep()</TT></TD><TD WIDTH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -