?? javaconc.html
字號(hào):
<li> <code>suspend()</code> halts a thread in a way that will continue normally after calling <code>resume()</code>. <li> <code>sleep()</code> and related methods cause objects to suspend and automatically resume in a controlled fashion, typically from within the running object itself. <li> <code>wait()</code> (which is defined in class <code>Object</code>, so is available to all Java objects) causes a thread to suspend until a later <code>notifyAll</code> or <code>notify</code> is made (nearly always within some other method of the object invoking the <code>wait</code>). <li> <code>yield()</code> yields control back to the scheduler (see below) so it can run other threads before returning to run more of this one.</ul><p> For example, here is a different kind of message printer (an exampleof the <a href="auton.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/auton.html">autonomous loop </a> pattern) that printsits message on average about every 5 seconds forever until stopped:<pre>public class SleepingMessagePrinter extends SimpleMessagePrinter { public SleepingMessagePrinter(String m, TextArea t) { super(m, t); } public void run() { for (;;) { try { Thread.currentThread().sleep((int)(Math.random() * 10000)); } catch (InterruptedException e) { return; } txt_.appendText(msg_); txt_.repaint(); } }}</pre><p>This can be driven from an Applet such as:<pre>public class SleepingMessageAppletV1 extends Applet { protected TextArea txt_; protected SleepingMessagePrinter hello_; protected SleepingMessagePrinter goodbye_; protected Thread ht_; protected Thread gt_; public SleepingMessageAppletV1() { txt_ = new TextArea(4, 40); txt_.setEditable(true); hello_ = new SleepingMessagePrinter("Hello\n", txt_); goodbye_ = new SleepingMessagePrinter("Goodbye\n", txt_); ht_ = new Thread(hello_); ht_.setDaemon(true); gt_ = new Thread(goodbye_); gt_.setDaemon(true); } public void init() { setLayout(new BorderLayout()); add("South", txt_); add("North", new Button("Stop")); } public void start() { ht_.start(); gt_.start(); } public boolean action(Event evt, Object arg) { if ("Stop".equals(arg)) { stop(); return true; } return false; } public void stop() { ht_.stop(); gt_.stop(); }}</pre><p><a href="SleepingMessageAppletV1.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/SleepingMessageAppletV1.html">Run SleepingMessageAppletV1</a>.<p>Notes:<ol> <li> The setDaemon(true) call establishes the message printers as <em>daemon</em> threads. The only difference between normal and daemon threads is that a java application is allowed to shut down once there are no more normal threads, but only daemon threads. It is usually a good idea to establish possibly infinitely looping threads as daemons. <li> The <code>sleep</code> method can throw <code>InterruptedException</code> if another thread interrupts it. The only sensible thing to do in this example is exit. </ol><h3>Scheduling and Priorities</h3>Unless you have better-than-average hardware, all of the activethreads in a Java application share the same CPU, which means thateach has to take turns executing for a while, and then being held in await queue while other threads get a chance to run, and so on. Andeven if you have multiple CPUs, you will still probably often havemore threads than CPUs. The scheduler that controls which threads geta chance to run uses <em>priorities</em> to decide which thread to runat any given time. Priorities are just numbers (between<code>Thread.MIN_PRIORITY</code> and <code>Thread.MAX_PRIORITY</code>)that help control scheduling.<p> When a thread is created to perform some possibly longcomputation, it is a good idea to give it a relatively low priority sothat other threads that deal with users will run instead whenever bothare in runnable states. If you don't do this, the rest of the program(especially the UI) will seem at best sluggish, and at worst will betotally unresponsive.<p> For a real example, the <AHREF="javascript:if(confirm('http://g.oswego.edu/dl/applets/micro.html \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl/applets/micro.html'" tppabs="http://g.oswego.edu/dl/applets/micro.html"> Microscope</A> gameis an applet that contains a slow automatic move finder. The <AHREF="javascript:if(confirm('http://g.oswego.edu/dl/classes/applets/Microscope.java \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://g.oswego.edu/dl/classes/applets/Microscope.java'" tppabs="http://g.oswego.edu/dl/classes/applets/Microscope.java"> code</A> setting up the move finder thread includes:<pre> public synchronized void startTurn(Board b, Player p) { if (!placing()) { initialBoard = b; initialPlayer = p; ... findThread = new Thread(this); findThread.setPriority(Thread.MIN_PRIORITY); findThread.start(); } }</pre><p><em>Note: This has the desired effect in JDK appletviewer, butfor unknown reasons, apparently not in Netscape-2beta5. </em><p> Another, less pleasant way to control scheduling is to placefrequent <code>yield()</code> calls in the worker codeitself. <code>Yield()</code> tells the scheduler to place the currentthread in the scheduling queue to give another thread a chance to runbefore getting back to the current one. However, if the current threadhas highest priority of those waiting, the yield may cause itimmediately resume anyway. (See the <a href="auton.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/auton.html"> AutonomousLoops</a> pattern for an example.)<blockquote>(Footnote: In most examples, we don't bother showing or dealing withpriorities. However, in general, it is a good idea to explicitlyset a priority whenever starting a new thread.)</blockquote><h3>ThreadGroups</h3>Every Java thread is created within a <code>ThreadGroup</code>.By default, each new thread is created to be in the same groupas its creator. ThreadGroups nest, so one whole ThreadGroup maybe part of another.<p> Threads within a ThreadGroup share some access and controlpolicies. For example, it is not legal to <code>stop</code> a threadthat is not in your group. This makes sure that, for example, a randomApplet doesn't kill the main Java screen display update loop thread.<p>The <code>ThreadGroup</code> class has some methods similar to thosein class <code>Thread</code>, but apply them to groups ofthreads instead of individuals.<p>Among the few common uses of ThreadGroups is to shut down all of thethreads associated with some task by calling<code>getThreadGroup().stop()</code>.<h2><a name="secSynch"></a>Synchronization</h2>So far, we've discussed only some variants of designs in which oneobject put a thread in motion, and then didn't have any interestingfurther interaction with it except perhaps to stop it. When objects inspawned threads run independently of <em>all</em> other activities andobjects in a program, you don't have to worry about the details ofasynchronous object interaction. But this is hardly ever the case.Even, or especially, when objects in different threads do not directlycommunicate, there is still the potential for indirect interactionwhen one object has methods invoked from those running in more thanone thread. For a simple example, two threads may both be setting andretrieving elements from the same data structure. What if an elementis only partially set by one object when it is accessed by the other?<p>Java provides a few general mechanisms for dealing with these issues, althoughyou have to work out the details on a case-by-case basis.<p>The general idea of programming cooperating asynchronous objects is that<br><blockquote><strong> Each object must protect ITSELF from any interference thatcould occur when participating in multiple threads. </strong></blockquote><p> The main Java construct that helps ensure this is the<code>synchronized</code> keyword. Any method marked as synchronizedis always executed in its entirety (unless explicitly suspended; forexample via a <a href="#secGuards"><code>wait</code></a>) before theobject is allowed to perform any other synchronized method calledfrom any other thread. <p> For example, consider an Applet Registry (somewhat like the existing<code>java.applet.AppletContext</code> class) where Applets can registerthemselves so that others can communicate with them.<p> We need to digress for a moment to figure out how to go aboutbuilding a registry. To work at all, a registry must be accessiblefrom all Applets. Since an Applet newly fired up from an HTML pagecould not know of the reference of an already-constucted registry, itwon't work to use normal Java objects. But there turns out to be aneasy way to do it using a variant of the <em>Facade</em> designpattern that uses an underlying <em>Singleton</em> (see the <AHREF="javascript:if(confirm('http://st-www.cs.uiuc.edu/users/patterns/Books.html \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://st-www.cs.uiuc.edu/users/patterns/Books.html'" tppabs="http://st-www.cs.uiuc.edu/users/patterns/Books.html"> DesignPatterns</A> book). We can build a <em>class</em> with all staticmethods, each of which hands off all functionality to a single normalJava helper object that does the real work. Since static methods needonly have the class name (not an object reference) to work, all iswell.<p>So the outwardly accessible Registry object is defined as follows:<pre>public class AppletRegistry extends Applet { static private AppletRegistryObject theRegistry = new AppletRegistryObject(); public AppletRegistry() { } public static void add(String nm, Applet app) { theRegistry.add(nm, app); } public static Applet get(String nm) { return theRegistry.get(nm); } public static int entries() { return theRegistry.entries(); } public static String nth(int i) { return theRegistry.nth(i); } public static void remove(String nm) { theRegistry.remove(nm); }}</pre><p><blockquote> (Footnote: This strategy could be recast as a moregeneral design pattern. For example, you could use the same scheme toset up a <em>ControlPanel</em> for multiple Applets. Unlike thosebased on the builtin <code>java.applet.AppletContext</code>, theapplets being controlled would not even need to be spawned from thesame HTML page.) </blockquote><p> The actual implementation class <code>AppletRegistryObject</code>here uses the simplest, barest data types (a stripped down variant ofa <a href="synchDesign.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/synchDesign.html">BoundedBuffer</a>) just to make thesynchronization issues clearer. The Registry is implemented using twofixed-sized arrays, one holding the names the objects will be accessedby, and the other the corresponding objects. We need to have methodsto register an applet by name, to access one by name, to delete anentry, and allow simple indexed access to support traversal. Surely,an AppletRegistry object should only be doing one of these things at atime, so each of these should be marked as synchronized:<blockquote><strong> Note: The following code is functional but onlyillustrative. If you build your own registry, please use moresensible data structures! </strong></blockquote><pre>class AppletRegistryObjectV0 { static private final int CAPACITY = 3; // for demo purposes private String names[] = new String[CAPACITY]; private Applet apps[] = new Applet[CAPACITY]; private int len = 0;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -