The client establishes a security manager and then calls Naming.lookup() to ask the
rmiregistry for a remote object reference. When it gets the reference, it then creates a pile of
ClientImpl objects and passes them as arguments to ro.frob(). And that's pretty much it.
The full source code for this program includes a lot of debugging statements that will print out
information about which thread is where and doing what. It is informative to examine the code in
more detail and watch its output. Compiling the program currently requires you to call a special
compiler, rmic, to build the stub code for the remote objects. (This may change.)
To run the program, you start the registry (Code Example 13-2), then the server, and finally, the
client. The registry needs to know the details of the class, so you must set CLASSPATH for it.
We'll simply start the registry from the code directory (as CLASSPATH includes ".")
Example 13-2 Running ServerRMI
bil@cloudbase[259]: rmic ServerImpl ClientImpl
bil@cloudbase[260]: rmiregistry &
bil@cloudbase[261]: java -DDEBUG Server &
Server: 'Frobber' now registered with rmiregistry.
bil@cloudbase[262]: java -DDEBUG Client &
RMI's Use of Threads
RMI starts up one thread to listen for remote invocations on the exported object. RMI's threading
behavior is not specified beyond this. All RMI says is that it will run your request in some thread
other than the ones you created. If you trace this program on Solaris 2.6, you will notice that the
server will run a bunch of remote requests in RMI thread 1, a few more in RMI thread 2, etc. It
will probably run multiple requests simultaneously in different threads. This is officially hidden
from you, and the only way to discover this is to print out the thread's name from frob().
The good part of this is that it doesn't matter. It's not part of your contract with RMI, so who cares?
The bad part is that if you mean to use RMI for high-performance programs, you have lost control
over the creation and number of threads that your server is running.
Exactly how and in which threads RMI executes remote requests is not specified, nor should it be.
All you care about is that your client made a remote invocation on an object and that methods
were run on the object in the server on some thread that you did not create.
In the reference implementation of Java 2, a single "accept" thread (TPC-Accept) is started when
the first object is exported [either via bind() or when you pass it as an argument to another
process]. This thread will listen on a dynamically allocated port for any and all incoming requests.
When a client connects and sends a request, the accept thread arranges for that request to run in a
TPC-Connection thread. If no connection threads exist, the accept thread will create one. If
there is an idle connection thread, the accept thread will use that. Idle connection threads
eventually exit.
There are no guarantees about which connection thread a request will run in or about how many
connection threads RMI will create. If your application needs absolute control over server threads,
you may have to build a consumer/producer model on top of RMI. In this case, the initial remote
method would place a request object on a queue and return a "working" message to the client.
When the consumer thread completes its work, it can return the desired results via a remote
invocation on a remote client-side object.
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks