Hi,
Ammendment:
This article may inappropriately suggest that a single threaded server-side
object using LockManager is significantly safer than a corresonding multi-
threaded object.
While the single-threaded, server-side object will contain less pitfalls, it is
not a cure-all. And, I apologize if I have suggested that. For any server-
side objects, whether single-threaded or multi-threaded, that access a shared
resource, such as the LockManager, must be appropriately coded as if
they were multi-threaded for that particular, critical part of the code.
***********************************
Threads003: Server-Side Strategies
***********************************
Please see this link
https://coderanch.com/t/185138/java-developer-SCJD/certification/NX-Exam-Locking-Issues where the two basic approaches
1. the
Multi-Threaded One Group, and
2. the
Single-Threaded N Group are defined.
Overview
--------
This article gives a broad comparison of the different RMI-based server-side
strategies, and gives my current opinion as to which is the best, both with
respect to the using of resources and with respect to avoiding multi-threaded
coding where it can be avoided.
Remote Objects
--------------
Depending on your design, the major remote object which the client uses to
communicate with the database is either called something like DataImpl or
MyServerImpl. For simplicity in this article, we will call this object
DataImpl, but either form of object might be used if your assignment does not
expressively forbid one or othe other.
Server-Side Strategies
----------------------
The first item in the following list I thought of this morning, and this
motivates the writing of this article:
These server-side strategies are now listed:
One question which I have asked, and which has not been answered yet (though,
of course it may have been answered in another
thread, or in a way which did
not register with me yet), is this:
is RMI a toy? Or is it a serious production-based, networked solution? That
is, how many clients can a normal, server support before the RMI system becomes
too slow?
I. Multi-Threaded One-Instance DataImpl Shell
----------------------------------------------
This is a server-side strategy I thought of this morning, and at this time is
quite probably how I will submit my exam. What I like about it is that if I
were designing a production-based, real-world RMI solution, I would chose this
solution; and, its multi-threaded complexity is low.
This section outlines a production-based solution; however, keep in mind that
I will most probably not implement a production-based solution since it is not
required for the exam; thus, some components of this solution I will not
implement, but the general concept I will most probably implement (or at least
investigate, for I never know what I will actually submit):
Diagram:
Concept: One DataImpl instance exists on the server. It delegates each
business request to a single-threaded new DataWorker; each DataWorker, being
single threaded, is easier to design, code and
test, but at the cost that each
new DataWorker temporarily uses up memory. When the DataWorker has carried out
the business method request, it can be garbage collected. The strains on
memory resources is short-lived, because DataWorker's life is short-lived.
A production-based solution might determine in advance the maximum allowable
number of instantiated DataWorker objects that will be allowed to exist on the
server at any given time (since you don't want the server to run out of memory).
This would be set in the server's preferences panel.
A production-based solution, if it already had the maximum number of DataWorker
objects instantiated and working, and another, new request came in, would find
a way to delay carrying out this request until one of the current DataWorker
objects was completed with its job. As it delays the requst, i.e., makes the
incoming thread wait(), it might also determine just how many incoming threads
in total can be made to wait (without exhausting memory or hogging the server's
memory), and then after some limit has been reached, inform the user that the
server is too busy.
A production-based solution might find a way to re-use DataWorker objects, so
you don't have to continually ask for a new one after an old one has carried
out a business method.
Be wary of making DataImpl overly complicated, however, since it is
multi-threaded.
II. Single-threaded N-Instance DataImpl
----------------------------------------
In this design, the Factory supplies the client with a unique, new, server-side
DataImpl which is single-threaded. This is somewhat similar to the first
design outlined in this article with the following difference: each instance
of DataImpl (one per client) continues to exist as long as the client is
connected to the server; for a production-based solution, I would not choose
this design as it could, given a sufficiently large number of users, exhaust
the server's memory. And, the number of RMI connections is unbounded.
Furthermore, another drawback is that each server-side DataImpl object, has a
life-time equal to that of how long each client stays connected, even though
the actual work the client does while connected with respect to needing the
server may be only 1/1000 or 1/10000 or 1/100000 of that time. For instance,
when you use a web site, you spend 1/10 of a second accessing the page from the
server, and you may spend one hour reading the web page.
III. Multi-threaded N-Instance DataImpl
----------------------------------------
"DataImpl_#1" means server-side instance number 1 of DataImpl. "DataImpl_#2"
means the second server-side instance of DataImpl, and so forth.
This is similar to the design given just above, but now each instance of
DataImpl is potentially mult-threaded and serves M clients (it would be
determined what the maximum number of clients one instance can serve efficiently
would be).
This is what happens for the default behavior of a
servlet within a servlet
container. Given one servlet class, then based upon the demand for that
servlet, the servlet container decides how many servlet instances will be
created, and how many client-request threads will be multi-threaded through
any given instance.
This was the design I was thinking of implementing until this morning I thought
of the first design outlined in this article.
Of course, here multi-threading issues abound, and it would take non-trivial
skill to implement DataImpl correctly in this multi-threaded environment.
A production version would dynamically instantiate DataImpl instances based
upon server demand, multi-thread them up to a certain maximum based upon
server demand, and destroy DataImpl instances when server demand drops. The
fact that RMI does not do this coding for you, that is, the fact that RMI does
not provide a servlet-like-container for you, may be what separates RMI as a
toy while servlets are considered production-ready paradigms.
IV. Multi-threaded One-Instance DataImpl
-----------------------------------------
Similar to the design given just above, but with heavy demand, would become
unresponsive sooner.
Thanks,
Javini Javono
[ February 14, 2004: Message edited by: Javini Javono ]
[ February 14, 2004: Message edited by: Javini Javono ]