posts - 496,comments - 227,trackbacks - 0

学习java tutorial中的rmi章节,读书笔记


JAVA-RMI 所采用的机制:

1. 某Object需要remote call ,则它所有的方法都放在一个新声明的接口中,该接口必须extends          Remote接口

   Compute接口中存放所有需要进行远程调用的方法,让实现该接口的类来实现这些被远程调用的方法

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    Object executeTask(Task t) throws RemoteException;
}


2.采用远程调用的方法同样有一些参数和返回值,对于这些参数和返回值,在不同JAVA虚拟机间传输,RM  I采取的是值传递,所以所有的参数和返回值必须extends Serializable

package compute;

import java.io.Serializable;

public interface Task extends Serializable {
    Object execute();
}


/*******************************************************************************************
上面为第一部分,在这当中,我们设计了一个接口,其中包含需要远程调用的方法,然后让该接口的实现者(即远程对象的owner)来实现这些方法
*******************************************************************************************/


3. 现在我们为了得到远程对象,就来实现一下上面定义的接口:
   main函数中,新建一个远程对象engine,并将它与名字name邦定:Naming.rebind(name, engine);

注:The superclass UnicastRemoteObject supplies implementations for a number of     java.lang.Object methods (equals, hashCode, toString) so that they are defined     appropriately for remote objects. UnicastRemoteObjectalso includes constructors and     static methods used to export a remote object, that is, make the remote object available     to receive incoming calls from clients.

package engine;

import java.rmi.*;
import java.rmi.server.*;
import compute.*;

public class ComputeEngine extends UnicastRemoteObject
                           implements Compute
{
    public ComputeEngine() throws RemoteException {
        super();
    }

    public Object executeTask(Task t) {
        return t.execute();
    }

    public static void main(String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }
        String name = "//host/Compute";
        try {
            Compute engine = new ComputeEngine();
            Naming.rebind(name, engine);
            System.out.println("ComputeEngine bound");
        } catch (Exception e) {
            System.err.println("ComputeEngine exception: " +
          e.getMessage());
            e.printStackTrace();
        }
    }
}

/*******************************************************************************************
上面为第二部分,在这当中,我们得到了一个实现了Compute接口的远程对象engine,注意:engine中只有那些Compute接口中的方法能够被远程调用,其他方法只能本地调用。现在,将远程对象engine邦定到RMI Registry 。 client可以从registry那里得到engine的引用,实际上是一个stub,相当于一个engine的代理,远程方法被client调用以后,可以改变engine的状态
*******************************************************************************************/
  
4. 下面我们实现那些远程方法调用时所要用到的参数:Task

package client;

import compute.*;
import java.math.*;

public class Pi implements Task {

    /** constants used in pi computation */
    private static final BigDecimal ZERO =
        BigDecimal.valueOf(0);
    private static final BigDecimal  ONE =
        BigDecimal.valueOf(1);
    private static final BigDecimal FOUR =
        BigDecimal.valueOf(4);

    /** rounding mode to use during pi computation */
    private static final int roundingMode =
        BigDecimal.ROUND_HALF_EVEN;

    /** digits of precision after the decimal point */
    private int digits;
   
    /**
     * Construct a task to calculate pi to the specified
     * precision.
     */
    public Pi(int digits) {
        this.digits = digits;
    }

    /**
     * Calculate pi.
     */
    public Object execute() {
        return computePi(digits);
    }

    /**
     * Compute the value of pi to the specified number of
     * digits after the decimal point.  The value is
     * computed using Machin's formula:
     *
     *          pi/4 = 4*arctan(1/5) - arctan(1/239)
     *
     * and a power series expansion of arctan(x) to
     * sufficient precision.
     */
    public static BigDecimal computePi(int digits) {
        int scale = digits + 5;
        BigDecimal arctan1_5 = arctan(5, scale);
        BigDecimal arctan1_239 = arctan(239, scale);
        BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
                                  arctan1_239).multiply(FOUR);
        return pi.setScale(digits,
                           BigDecimal.ROUND_HALF_UP);
    }
    /**
     * Compute the value, in radians, of the arctangent of
     * the inverse of the supplied integer to the speficied
     * number of digits after the decimal point.  The value
     * is computed using the power series expansion for the
     * arc tangent:
     *
     * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 +
     *     (x^9)/9 ...
     */  
    public static BigDecimal arctan(int inverseX,
                                  int scale)
    {
        BigDecimal result, numer, term;
        BigDecimal invX = BigDecimal.valueOf(inverseX);
        BigDecimal invX2 =
            BigDecimal.valueOf(inverseX * inverseX);

        numer = ONE.divide(invX, scale, roundingMode);

        result = numer;
        int i = 1;
        do {
            numer =
                numer.divide(invX2, scale, roundingMode);
            int denom = 2 * i + 1;
            term =
                numer.divide(BigDecimal.valueOf(denom),
                             scale, roundingMode);
            if ((i % 2) != 0) {
                result = result.subtract(term);
            } else {
                result = result.add(term);
            }
            i++;
        } while (term.compareTo(ZERO) != 0);
        return result;
    }
}

5. 最后我们实现client对象
   远程对象comp是通过RMI的注册表来查找到的

package client;

import java.rmi.*;
import java.math.*;
import compute.*;

public class ComputePi {
    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }
        try {
            String name = "//" + args[0] + "/Compute";
            Compute comp = (Compute) Naming.lookup(name);
            Pi task = new Pi(Integer.parseInt(args[1]));
            BigDecimal pi = (BigDecimal) (comp.executeTask(task));
            System.out.println(pi);
        } catch (Exception e) {
            System.err.println("ComputePi exception: " +
                               e.getMessage());
            e.printStackTrace();
        }
    }
}

posted on 2008-04-03 13:25 SIMONE 阅读(778) 评论(1)  编辑  收藏 所属分类: rmi

FeedBack:
# re: JAVA-RMI学习心得
2008-05-13 11:21 | 状元郎
ICE是个很有潜力的中间件架构。语言中立。性能很好。
据说是用来替代CORBA和RMI的。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: