Java Reference
In-Depth Information
The code for
RmiFactoryExample
is very similar, with the following differences in the
main
method:
Naming.rebind("RmiFactoryExample", new DvdDatabaseFactoryImpl());
Listing 6-6 shows the
run
method for
RmiFactoryExample
.
Listing 6-6.
The Main Method in the RmiNoFactoryExample Class
public void run() {
try {
System.out.println("Getting a remote handle to a factory. "
➥
+ this.hashCode());
DvdDatabaseFactory factory
= (DvdDatabaseFactory)Naming.lookup("RmiFactoryExample");
DvdDatabaseRemote worker = factory.getClient();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
To run the
RmiNoFactoryExample
test program, type the following command in the
classes
directory of the
sampleproject
:
java sampleproject.remote.RmiNoFactoryExample
And to run the
RmiFactoryExample
, type:
java sampleproject.remote.RmiFactoryExample
Figure 6-10 shows the output of running the two test programs.
In the
DvdDatabase
class, an output line was added to indicate that the constructor was
called. The following
println
statement has been inserted into the
DvdDatabase
constructor:
System.out.println(" constructing a DvdDatabase object " + this.hashCode());
Examining the output of the two test programs indicates a critical difference: the
number of
DvdDatabase
objects constructed. The
RmiFactoryExample
constructs two separate
instances of the object. The
RmiNoFactoryExample
constructs only one. This demonstrates
how RMI reuses threads. Each thread has a separate
DvdDatabase
object, but since the
RmiNoFactoryExample
reuses one of the threads, the
DvdDatabase
instance is shared between
the two remote invocations. Thus we cannot ensure thread safety and our locking strategy
fails. (Refer to the section in Chapter 5 on locking to review why the locking strategy requires
a unique
DvdDatabase
object.)