?? early.html
字號(hào):
<html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><html> <head><title>Early Reply Threads</title></head><BODY bgcolor=#ffffee vlink=#0000aa link=#cc0000><h1>Early Reply Threads</h1>Some kinds of threads arise in designs where a server initiates a newlogically asynchronous activity whenever it receives a particular kindof message. This pattern applies whenever it makes sense to have aServer, not a Client control thread creation. (For client-controlledthread construction, see <a href="waiters.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/waiters.html">Waiter</a> and <ahref="service.html" tppabs="http://www.foi.hr/~dpavlin/java/mirrors/g.oswego.edu/dl/pats/service.html">Service</a> Thread patterns.)<p> One way to conceptualize such designs is through the notion of an<EM>Early Reply</EM>. Early Reply is a construct found natively insome concurrent OO programming languages (e.g., <ahref="javascript:if(confirm('http://www2.hursley.ibm.com/orexx/ \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://www2.hursley.ibm.com/orexx/'" tppabs="http://www2.hursley.ibm.com/orexx/">OREXX</a>) and implementablevia other mechanisms in others (including Java). Early replyconstructs mesh nicely with the synchronous nature of normal OOmessage sends, while at the same time supporting concurrency (see <AHREF="javascript:if(confirm('http://g.oswego.edu/dl/oosdw3/ch20/ch20.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/oosdw3/ch20/ch20.html'" tppabs="http://g.oswego.edu/dl/oosdw3/ch20/ch20.html">OOSD, Chapter20</A>). To illustrate, suppose for a moment that Java had a<CODE>reply</CODE> construct, as in:<PRE>class Server2 { public synchronized int m1() { int result = computeResult(); reply result; // (*) activityPart1(); activitypart2(23); } void synchronized activityPart1() { /* ... */ } void synchronized activityPart2(int j) { /* ... */ }}</PRE>The idea is that at point <CODE>(*)</CODE>, one thread of controlreturns to the caller, and another runs (<CODE>activityPart1()</CODE>followed by <CODE>activityPart2()</CODE>), asynchronously with respectto the caller.<p>Java does not support this notion directly, but itdoes supply a built-in method that uses early reply, the<CODE>start()</CODE> method in class <CODE>Thread</CODE>. This turnsout to suffice for programming all other forms of early replies. (Infact, it is the basis for <EM>all</EM> asynchrony in Java.) The basicrecipe is:<OL><LI> Mostly just for convenience, if not already so defined, define a single method in the server that when invoked runs all aspects of the asynchronous activity.<LI> Define a Runnable class, say <CODE>Activity</CODE>, with: <UL> <LI> An instance variable holding a reference to the service object; <LI> Instance variables holding each argument to the activity method; <LI> A constructor that initializes these variables; <LI> A <CODE>run</CODE> method that ``calls back'' the service object to run the activity. </UL> (As described <a href="#secCombine">below</a>, in some cases this class may actually be the same as the server class itself.) <LI> End the method that spawns the new activity with <BR><CODE> (new Thread(new Activity(this, ...))).start(); return x;</CODE> <BR> where <CODE>x</CODE> is the return value, if any.<LI> Ensure that all relevant methods are <CODE>synchronized</CODE>. (We do this routinely in these patterns, but it is especially critical in this construction, since the thread calls back the host object to perform the activity, interleaved with anything else it might be doing.)<LI> Consider whether and how you need to limit thread construction. (This issue is ignored until <a href="#secLimiting">later</a>.)</UL>Applied to the above example, we have:<PRE>class Server2Activity implements Runnable { private Server2 s_; private int j_; public Server2Activity(Server2 s, int j) { s_ = s; j_ = j; } public void run() { s_.doActivities(j_); }}class Server2 { public synchronized int m1() { int result = computeResult(); (new Thread(new Server2Activity(this, 23))).start(); return result; } void synchronized doActivities(int j) { activityPart1(); activityPart2(j); } void synchronized activityPart1() { /* ... */ } void synchronized activityPart2(int j) { /* ... */ }}</PRE><H3><A NAME="secSubj">Subject/Observer</H3>As a less arbitrary example of early-reply threads, consider thefollowing subject/observer design, as described in 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. (See also their <AHREF="javascript:if(confirm('http://g.oswego.edu/dl/ProtocolCharts/PC.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/ProtocolCharts/PC.html'" tppabs="http://g.oswego.edu/dl/ProtocolCharts/PC.html">ProtocolChart</A> description.) <P>In the Subject/Observer pattern, <EM>Subjects</EM> maintain some kindof representation of the state of something they are modeling, alongwith operations to reveal and change this state. <EM>Observers</EM>somehow display (or otherwise use) the state represented by Subjects.When a Subject's state is changed, it merely informs one or moreobservers that it has changed. Observers are responsible for probingthe subjects to determine the nature of the changes, and whether, forexample, they require re-display. <P>For simplicity, in this version, the <CODE>state</CODE> maintained bythe <CODE>Subject</CODE> is represented as a single <CODE>int</CODE>,and each <CODE>Observer</CODE> maintains a reference to a single<CODE>Subject</CODE>, and the list of observers is maintained using a<code>Bag</code> from the <ahref="javascript:if(confirm('http://g.oswego.edu/dl/classes/collections \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/collections'" tppabs="http://g.oswego.edu/dl/classes/collections">collectionspackage</a>.<p>A single-threaded version looks like:<PRE>class Subject { private int state_; // the modeled state private collections.UpdatableBag obs_; // observers of this subject /* Adding and removing Observers */ public synchronized void attach(Observer ob) { obs_.addIfAbsent(ob); } public synchronized void detach(Observer ob) { obs_.exclude(ob); } /* Revealing modeled state */ public synchronized int state() { return state_; } /* Changing state causes update messages to be sent to each observer */ public synchronized void state(int newstate) { state_ = newstate; for (Enumeration e = obs_.elements(); e.hasMoreElements(); ) ((Observer)(e.nextElement())).update(); } public Subject(int initstate) { state_ = initstate; obs_ = new collections.Dynarray(); }}class Observer { private int cachedState_; private Subject subj_; /* Process an update: if subj state has changed from old value, redisplay */ public synchronized void update() { int oldState = cachedState_; cachedState_ = subj_.state(); if (oldState != cachedState_) display(); } /* a stand-in for a real display method */ synchronized void display() {
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -