44.

previous chapter table of contents next chapter
  

Running Threads from Discovery

The previous section looked at issues involving the location of classes in order to reduce network traffic and to improve the speed and responses of clients and services. Within a client or service, other techniques, such as multithreading, can also be used to improve responsiveness.

In all of the examples using explicit registration (such as those in 9), a single thread was used. That is, as a service locator was discovered, the registration process commenced in the same thread. This registration may take some time, and during this time, new lookup services may be discovered . To avoid the possibility of these new services timing out and being missed, all registration processing should be carried out in a separate thread, rather than possibly holding up the discovery thread.

Server Threads

Running another thread is not a difficult procedure. Basically we have to define a new class that extends Thread, and move most of the registration into its run method. This is done in the following version of the file classifier server, which is based on the server in Chapter 3 that uploads a complete service. In this version, the registration code is moved to a separate thread, which is implemented using an inner class:

 package complex; import complete.FileClassifierImpl; import java.rmi.RMISecurityManager; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.DiscoveryListener; import net.jini.discovery.DiscoveryEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceRegistration; import net.jini.core.lease.Lease; // import com.sun.jini.lease.LeaseRenewalManager; // import com.sun.jini.lease.LeaseListener; // import com.sun.jini.lease.LeaseRenewalEvent; import net.jini.lease.LeaseRenewalManager; import net.jini.lease.LeaseListener; import net.jini.lease.LeaseRenewalEvent; /**  * FileClassifierServer.java  */ public class FileClassifierServer implements DiscoveryListener,                                              LeaseListener {     protected LeaseRenewalManager leaseManager = new LeaseRenewalManager();     public static void main(String argv[]) {         new FileClassifierServer();         // keep server running forever to         // - allow time for locator discovery and         // - keep re-registering the lease         Object keepAlive = new Object();         synchronized(keepAlive) {             try {                 keepAlive.wait();             } catch(InterruptedException e) {                 // do nothing             }         }     }     public FileClassifierServer() {         LookupDiscovery discover = null;         try {             discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);         } catch(Exception e) {             System.err.println(e.toString());             System.exit(1);         }         discover.addDiscoveryListener(this);     }     public void discovered(DiscoveryEvent evt) {           ServiceRegistrar[] registrars = evt.getRegistrars();           for (int n = 0; n < registrars.length; n++) {             ServiceRegistrar registrar = registrars[n];             new RegisterThread(registrar).start();          }     }     public void discarded(DiscoveryEvent evt) {     }     public void notify(LeaseRenewalEvent evt) {         System.out.println("Lease expired " + evt.toString());     }     /**      * an inner class to register the service in its own thread      */     class RegisterThread extends Thread {         ServiceRegistrar registrar;         RegisterThread(ServiceRegistrar registrar) {             this.registrar = registrar;         }         public void run() {             ServiceItem item = new ServiceItem(null,                                                new FileClassifierImpl(),                                                null);             ServiceRegistration reg = null;             try {                 reg = registrar.register(item, Lease.FOREVER);             } catch(java.rmi.RemoteException e) {                 System.err.println("Register exception: " + e.toString());                 return;             }             System.out.println("service registered");             // set lease renewal in place             leaseManager.renewUntil(reg.getLease(), Lease.FOREVER,                                     FileClassifierServer.this);         }     } } // FileClassifierServer 

Join Manager Threads

If you use a JoinManager to handle lookup and registration, then it essentially does this for you: it creates a new thread to handle registration. Thus, the examples in Chapter 11 do not need any modification, as the JoinManager already uses the concepts of this section.

Client Threads

It is probably more important to use threads in the client than in the server, because the client will actually perform some computation (which may be lengthy) based on the service it discovers. Again, this is a simple matter of moving code into a new class that implements Thread . Doing this to the multicast client TestFileClassifier of Chapter 3 results in the following code:

 package client; import common.FileClassifier; import common.MIMEType; import java.rmi.RMISecurityManager; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.DiscoveryListener; import net.jini.discovery.DiscoveryEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceTemplate; /**  * TestFileClassifierThread.java  */ public class TestFileClassifierThread implements DiscoveryListener {       public static void main(String argv[]) {         new TestFileClassifierThread();         // stay around long enough to receive replies         try {             Thread.currentThread().sleep(10000L);         } catch(java.lang.InterruptedException e) {             // do nothing         }     }                   public TestFileClassifierThread() {         System.setSecurityManager(new RMISecurityManager());         LookupDiscovery discover = null;         try {             discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);         } catch(Exception e) {             System.err.println(e.toString());             System.exit(1);         }         discover.addDiscoveryListener(this);     }     public void discovered(DiscoveryEvent evt) {                               ServiceRegistrar[] registrars = evt.getRegistrars();                                   for (int n = 0; n < registrars.length; n++) {             System.out.println("Service found");             ServiceRegistrar registrar = registrars[n];             new LookupThread(registrar).start();         }     }     public void discarded(DiscoveryEvent evt) {         // empty     }     class LookupThread extends Thread {         ServiceRegistrar registrar;         LookupThread(ServiceRegistrar registrar) {             this.registrar = registrar;         }         public void run(){             Class[] classes = new Class[] {FileClassifier.class};             FileClassifier classifier = null;             ServiceTemplate template = new ServiceTemplate(null, classes,                                                            null);             try {                 classifier = (FileClassifier) registrar.lookup(template);             } catch(java.rmi.RemoteException e) {                 e.printStackTrace();                 return;             }             if (classifier == null) {                 System.out.println("Classifier null");                 return;             }             MIMEType type;             try {                 type = classifier.getMIMEType("file1.txt");                 System.out.println("Type is " + type.toString());             } catch(java.rmi.RemoteException e) {                 System.err.println(e.toString());             }         }     } } // TestFileClassifier 
  


A Programmer[ap]s Guide to Jini Technology
A Programmer[ap]s Guide to Jini Technology
ISBN: 1893115801
EAN: N/A
Year: 2000
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net