?? waiters.html
字號:
<html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><html> <head><title>Waiters</title></head><BODY bgcolor=#ffffee vlink=#0000aa link=#cc0000><h1>Waiters</h1>A waiter thread is a thread constructed by a client when it does notwant or need to block waiting for a normal method call to some otherobject to complete, but instead allows the call to proceed asynchronously.<p> Waiter threads provide a way to simulate the effects ofasynchronous ``oneway'' message passing (as is supported in mostdistributed object frameworks) within the confines of a single Javaprogram.<p>Any method call can be transformed to use a waiter.However, this pattern is most appropriate when one or moreof the following conditions hold:<ul> <li> The called method is one that <em>most</em> callers would normally want to wait out. (Otherwise, it might be better to transform the called method into a <a href="service.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/service.html"> service thread</a>. Waiters deal with only one particular call to a method, while service thread machinations transform the method itself.) <li> The called method is time consuming enough to outweigh <a href="when.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/when.html">thread start-up overhead</a>. (Otherwise, even though the method call may be logically asynchronous, it may be better just to call it normally.) <li> The called method returns useful results that the client may later want to know about, but doesn't otherwise want to wait out. <li> The called method may raise exceptions that the client would like to know about and deal with, but doesn't want to actually catch itself. <li> The called method sometimes blocks for indeterminate periods (due to <a href="synchDesign.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/synchDesign.html"> synchronization delays</a>), but the client cannot tolerate indefinite delays. <li> The called method is part of a class that you are not allowed to modify. (Otherwise, modifying it to be either a <a href="service.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/service.html">service thread </a> or <a href="early.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/early.html"> early reply</a> thread might be better.) <li> The client would like to run the method independently for a while in order to do other things, but to later just wait it out to completion and/or time-out on the wait to take some evasive action if it does not complete within some specified time. </ul>For example, consider original code:<PRE>class Server1 { public synchronized void m(int k) { aLongComputation(k); }}class Client1 { public synchronized void p(Server1 s) { s.m(17); somethingElse(); }} </PRE>But where we'd like the <code>s.m(17)</code> call to behave as anasynchronous message, performed independently by <code>s</code>without blocking the <code>Client1</code>. This effect may beobtained by via the following recipe. The recipe is very easy tofollow, but at the same time somewhat awkward since you need to definea new helper class that is often too specialized to the context inwhich it is used to be useful/reusable in other situations:<OL><LI> Define a Runnable class, say <CODE>Waiter</CODE> with: <UL> <LI> An instance variable holding a reference to the target object; <LI> Instance variables holding each argument to the target method; <LI> A constructor that initializes these variables; <LI> (When applicable) instance variables and associated access methods holding any return values or exceptions from the called method. <LI> A <CODE>run</CODE> method that invokes the target method accordingly with the supplied arguments, and places any results in instance variables. <LI> (Optional) an instance variable and/ access method, say <code>boolean done()</code>, that the client can call to check the status of the call. Or alternatively, support for <a href="service.html#secCallbacks" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/service.html#secCallbacks">completion callbacks</a>. </UL><LI> Instead of directly invoking the target method, have the client construct a new instance of the <CODE>Waiter</CODE>, and run it in a thread.</OL><p>Applying this to the above example, we have:<PRE>class Server1 { public synchronized void m(int k) { aLongComputation(k); }}class Server1_m_Waiter implements Runnable { private Server1 s_; private int k_; private boolean done_; public Server1_m_Waiter(Server1 s, int k) { s_ = s; k_ = k; done_ = false; } public void run() { s_.m(k_); done_ = true; } public synchronized void done() { return done_; }}class Client1 { public synchronized void p(Server1 s) { (new Thread(new Server1_m_Waiter(s, 17))).start(); somethingElse(); }} </PRE><blockquote>Footnote: If you ignore the thread mechanics, waiter constructions may beseen as variant forms of <em>closures</em>; similar for example tothose defined in <code>[ ... ]</code> blocks in smalltalk, and usablein the same kinds of contexts that you would use blocks insmalltalk. It is even possible to build tools in Java to define suchclosure classes automatically.</blockquote><h2><a name="secJoin"></a>Joining</h2><EM>Futures</EM> (also known as <EM>deferred synchronous</EM> calls)are a common variant of Waiters in which the result and exceptionvariables and accessors listed above are implemented, and where theclient actually blocks waiting for termination only when it happens toneed the result. In some concurrent OO languages, futures arebuilt-in constructs and this conditional blocking is performedautomatically by the run-time system. But it is easy enough, and moreflexible to do this manually in Java.<p> You can use the <code>Thread.join</code> method to have a clientwait for the thread to complete at a later time. For example, suppose<code>Client1</code> above wants to make sure that the call iscompleted before ultimately returning. This could be arranged by:<PRE>class Client2 { public synchronized void p(Server1 s) { Thread t = new Thread(new Server1_m_Waiter(s, 17)); t.start(); somethingElse(); try { t.join(); } catch(InterruptedException ex) { return; } }} </PRE><p> Another version, <code>Thread.join(long milliseconds)</code> canbe used to obtain calls with <em>Time-outs</em>. This version of joinreturns when either the thread is done, or the indicated time haselapsed, or it receives an <code>InterruptedException</code>. Forexample, suppose we wanted to cancel the above call if it had notcompleted in 1 second (counting time from the <code>join</code> call,not the <code>start</code> call):<PRE>class Client3 { public synchronized void p(Server1 s) { Server1_m_Waiter w = new Server1_m_Waiter(s, 17); Thread t = new Thread(w); t.start(); somethingElse(); try { t.join(1000); } catch(InterruptException ex) { return ; } t.stop(); // either has no effect (if already done) or stops (if timeout) if (!w.done()) { /* ... take evasive action ... */ } }} </PRE><p> Join-based designs can be generalized so that clients spawn offany number of waiter threads (not just one), and then continue alongonly when they are all finished. This is one way to obtain the effectsof <em>cobegin ... coend</em> style concurrent programming, ``barriersynchronization'' style parallel programming, and multicast styledistributed programming. For example, suppose we wanted to set inmotion two different calls to <code>s.m()</code>, but not to returnuntil both were finished:<PRE>class Client4 { public synchronized void p(Server1 s) { Server1_m_Waiter w1 = new Server1_m_Waiter(s, 17); Server1_m_Waiter w2 = new Server1_m_Waiter(s, 666); Thread t1 = new Thread(w1); Thread t2 = new Thread(w2); t1.start(); t2.start(); somethingElse(); try { t1.join(); } catch(InterruptedException ex) { t2.stop(); return; } try { t2.join(); } catch(InterruptedException ex) { return; } }} </PRE>By adding <a href="service.html#secCallbacks" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/service.html#secCallbacks"> completion callbacks</a>, this design could be changed so that as soon as <em>either</em>of <code>t1</code> or <code>t2</code> terminate, the other one isstopped, and the method returns. This is a common strategy forimplementing parallel search algorithms where each thread looks at adifferent subset of a database.<p><a href="aopintro.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/aopintro.html">[Concurrent Programming in Java]</a><hr><address><A HREF="javascript:if(confirm('http://g.oswego.edu/dl \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'" tppabs="http://g.oswego.edu/dl">Doug Lea</A></address><!-- hhmts start -->Last modified: Tue Feb 20 06:27:19 EST 1996<!-- hhmts end --></body> </html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -