RMI异步回调方法调用

基于RMI支持异步方法调用支持优先级队列

包1:

客户端:

public class Client {
    public static void main(String args []){
        Axman proxy = null ;
        try {
            proxy = (Axman) Naming.lookup("rmi://localhost:5555/Axman");
            System.out.println("客户端:已查找到服务器!");
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NotBoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

         //(内容,代理,优先级)
        new ResultInvokeThread("A", proxy, 0).start();
        new ResultInvokeThread("B", proxy, 1).start();
        new ResultInvokeThread("C", proxy, 2).start();
        
    }
}

回调接口实现:

public class CallbackResultImpl extends UnicastRemoteObject implements CallbackResult {
    public CallbackResultImpl() throws RemoteException {
        super();
    }

    private boolean complete = false;
    private RealResult result;
    //锁住这个对象实例o
    public synchronized RealResult getResult() {
        while(!complete){
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     *
     */
    private static final long serialVersionUID = -1231685934061368147L;

    /**
     *  1.执行这个的线程在客户端中,客户端会派一个新线程来执行这段程序
     *  2.服务端在这个方法里一直与客户端保持连接,如果客户端断开,那么服务器抛异常,
     *  因为它一直等客户端告诉他是否执行完,执行完了他才能执行下面的程序
     *  3.如果服务端断开,那么客户机还会继续执行这段程序,不受影响
     *  4.因此可以用notify和wait,因为这个两个线程都在客户端jvm中
     */
    public synchronized void getRealResult(RealResult result) throws RemoteException {
        this.result = result;
        this.complete = true;
        this.notify();
    }

    public boolean isComplete() throws RemoteException {
        return complete;
    }

}

客户端模拟方法调用的线程:

public class ResultInvokeThread extends Thread {
    private  Axman ao = null ;
    private  String rc  = null;
    private  int level  = 0;

    /**
     *
     * @param content
     *            请求名称
     * @param ao
     * @param level
     *            请求级别
     */
    public ResultInvokeThread(String content, Axman ao, int level) {
        this.ao = ao;
        this.rc = content;
        this.level = level;
    }
    
    public ResultInvokeThread() {
        super();
    }

    public void run() {
        try {
            int i = 0;
            while (i < 2) {
                System.out.println("客户端:产生一个新请求" + rc + i);
                // 这个是futureResult,里面还没有内容
                CallbackResultImpl o = new CallbackResultImpl();
                this.ao.resultTest(rc+(i++), level,o);
                // 程序会在这里阻塞5秒等future.setResult(RealResult)
                RealResult r = o.getResult();
                System.out.println("客户端:请求结果到达!"+r.getResult().toString());
            }
        } catch (Throwable t) {
        }
    }

    
}

包2:

服务端:

public class Server {


    public static void main(String[] args) {

        try {
            Axman proxy = AxmanFactory.createAxman();
            // 本地主机上的远程对象注册表Registry的实例,并指定端口为5555,这一步必不可少(Java默认端口是1099),
            // 必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上
            LocateRegistry.createRegistry(5555);
            // 把远程对象注册到RMI注册服务器上,并命名为RTranslate
            // 绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略)
            Naming.bind("rmi://localhost:5555/Axman", proxy);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("服务器:已绑定成功!");

    }

}


/**
 * 忠心做真实的事务

 * @author Administrator
 *
 */
public class Servant {
    /**
     * @return
     * @throws RemoteException
     *
     */
    public RealResult resultTest(String requestContent,int level,CallbackResult g) throws RemoteException {

            try {        
                //模拟做事情耗时
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        return new RealResult(requestContent);

    }

}

/**
 * 对容器中的请求根据一定原则进行调度执行

 * @author Administrator
 *
 */
public class Scheduler extends Thread {

    private final ActivationQueue queue;

    public Scheduler(ActivationQueue queue) {

        this.queue = queue;

    }
    /**
     *
     * @param request
     */
    public void invoke(MethodRequest request) {
        this.queue.putRequest(request);    
        System.out.println("+放进队列一个请求");
        
    }

    public void run() {

        while (true) {

            // 如果队列中有请求线程 , 则开始执行请求        
            MethodRequest request = this.queue.takeRequest();    
            System.out.println("-拿出队列一个请求");
            //一次只能执行一个请求,阻塞在这里
            request.execute();
        }

    }

}

public class ResultRequest extends MethodRequest {
    private final String rc;

    public ResultRequest(Servant servant,
            String requestContent, int level, CallbackResult g) {
        super(servant, level, g);
        this.rc = requestContent;
    }

    public void execute() {
        RealResult result = null;
        try {
            result = servant.resultTest(this.rc, level, g);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            //回调的时候才与客户端进行连接
            g.getRealResult(result);
        } catch (RemoteException e) {
            System.out.println("服务器:客户端连接断开!");
            e.printStackTrace();
        }
        System.out.println("完成一个有参请求!返回结果中...");
    }
}

有参数的方法调用的真实结果:

public class RealResult implements Serializable{
      private final Object result;
      
      public RealResult(Object result) throws RemoteException{
        this.result = result;
      }
      public Object getResult(){
        return this.result;
      }
    
}

/**
 * 把要调用的方法转换为对象的保程不仅仅是可以对要调用的方法进行调度
 * @author Administrator
 */
public class Proxy extends UnicastRemoteObject implements Axman {

    /**
     *
     */
    private static final long serialVersionUID = -4796083772704736050L;

    private final Scheduler scheduler;

    private final Servant servant;

    public Proxy(Scheduler scheduler, Servant servant) throws RemoteException{

        this.scheduler = scheduler;

        this.servant = servant;

    }
    
    public void resultTest(String requestContent,int level,CallbackResult g) throws RemoteException{
        this.scheduler.invoke(new ResultRequest(servant,requestContent,level,g));//把请求放进队列
    }


}

远程方法接口

public interface Axman extends Remote {

    void resultTest(String requestContent, int level, CallbackResult g)
            throws RemoteException;
}
public abstract class MethodRequest {

      protected final Servant servant;
      protected final int level;
      protected CallbackResult g;
      protected MethodRequest(Servant servant,int level,CallbackResult g){
        this.servant = servant;
        this.level = level;
        this.g = g;
      }

      public abstract void execute();
}

回调接口

public interface CallbackResult extends Remote{
    void getRealResult(RealResult result) throws RemoteException;
}

public class AxmanFactory {
    public static Axman createAxman() throws RemoteException {
        Servant s = new Servant();
        ActivationQueue queue = new ActivationQueue();
        Scheduler st = new Scheduler(queue);
        Proxy p = new Proxy(st,s);
        st.start();
        return p;
      }

}

/**
 * 将请求缓存起来以便调度

 * @author Administrator
 *
 */
public class ActivationQueue {

    private static final int MAX_METHOD_REQUEST = 100;

    //优先级队列
    private Queue<MethodRequest> requestQueue;  
    
    private int count;

    public ActivationQueue() {
         Comparator<MethodRequest> rule =  new Comparator<MethodRequest>(){  
                public int compare(MethodRequest r1, MethodRequest r2) {  
                    int numbera = r1.level;  
                    int numberb = r2.level;
                    //级别高的优先
                    if(numberb > numbera)  
                    {  
                        return 1;  
                    }  
                    else if(numberb < numbera)  
                    {  
                        return -1;  
                    }  
                    else  
                    {  
                        return 0;  
                    }  
                  
                }
         };
        this.requestQueue = new PriorityQueue<MethodRequest>(MAX_METHOD_REQUEST,rule);
        this.count = 0;

    }

    public synchronized void putRequest(MethodRequest request) {
         while(this.count >= MAX_METHOD_REQUEST){
              try {
                this.wait();
              }
              catch (Throwable t) {}
            }
        requestQueue.add(request);  
        count ++ ;
        System.out.println("目前队列请求数:"+count);
        this.notifyAll();
        

    }

    public synchronized MethodRequest takeRequest() {
        while(this.count <= 0){
              try {
                this.wait();
              }
              catch (Throwable t) {}
        
            }

        MethodRequest request  = requestQueue.poll();    
        count --;
        System.out.println("目前队列请求数:"+count);
        this.notifyAll();
        return request;

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值