句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。
分布式计算时解决大型应用的一种重要手段。它指的是一种应用程序的的设计模式,其中程序,数据,计算能力都分布在网络中。
RMI(远程方法调用)是不同的java虚拟机之间的对象间进行通信的规范。
远程对象:另外一个虚拟机中对象。这类对象被接口描述,这些接口实现声明了远程对象的方法。
远程方法调用:对一个远程对象中的接口中的方法进行调用。
实现不同JAVA虚拟机之间应用程序之间通信技术区别:
1.套接字,通过应用级协议进行通信,要求应用程序之间必须使用相同协议。
2.JMS(JAVA消息服务),对象在物理上被异步的从网络的某个JVM直接移动到另一个JVM。
3.RMI(远程方法调用),RMI对象是绑定在本地JVM中,只有函数参数和返回值是通过网络传送的。
一个RMI会话系统:
1》定义远程接口
2》实现这个接口
3》生成stub(客户代理)和skeleton(服务器实体)
4》编写远程对象的客户程序
5》启动注册表并登记远程对象
6》运行服务器和客户程序
参考博客:http://blog.csdn.net/qq_30114557/article/details/69390714?locationNum=14&fps=1(运行步骤)
(1) 在执行 rmiregistry 之前,设置classpath让能查找到PerfectTime_Stub类,如在同一Dos窗口中,假设 PerfectTime_Stub类是在E:\workspace\TestRMI\bin目录中,执行过程那就是
C:\Documents and Settings\unmi>set classpath=%classpath%;E:\workspace\TestRMI\bin
C:\Documents and Settings\unmi>rmiregistry 2005
有了远程接口及其实现以后,就需要在注册表中对它进行绑定,以使客户能获得该对象。
服务器接口:
package rmiTest;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMITest1I extends Remote{
long getPerfectTime() throws RemoteException;
}
实现服务器接口的类:
package rmiTest;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RMITest1 extends UnicastRemoteObject implements RMITest1I{
public RMITest1() throws RemoteException {
// TODO Auto-generated constructor stub
super();
}
@Override
public long getPerfectTime() throws RemoteException {
// TODO Auto-generated method stub
return System.currentTimeMillis();
}
@SuppressWarnings("deprecation")
public static void main(String[] args){
try{
RMITest1 rt=new RMITest1();
Naming.rebind("rmi://localhost:1099/RMITest1", rt);
System.out.println("Bind OK!");
}catch(Exception e){
e.printStackTrace();
}
}
}
客户端代码:
package rmiClient;
import java.rmi.Naming;
import rmiTest.RMITest1I;
public class DisplayPerfectTime {
public DisplayPerfectTime() {
// TODO Auto-generated constructor stub
super();
}
public static void main(String[] args) {
try{
RMITest1I t=(RMITest1I) Naming.lookup("rmi://localhost:1099/RMITest1");
for(int i=0;i<10;i++){
System.out.println("PerfectTime:"+t.getPerfectTime());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
带有回调的RMI会话
Java ConcurrentModificationException 异常分析与解决方案(http://www.2cto.com/kf/201403/286536.html)
服务程序
package rmiServer;
import java.rmi.Remote;
import java.rmi.RemoteException;
import rmiClient.RMIClientI;
public interface RMIServerI extends Remote{
//客户程序应该实现的远程接口
public void registerClient(RMIClientI client) throws RemoteException;
public void unregisterClient(RMIClientI client) throws RemoteException;
}
package rmiServer;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashSet;
import java.util.Iterator;
import rmiClient.RMIClient;
import rmiClient.RMIClientI;
@SuppressWarnings("serial")
public class RMIServer extends UnicastRemoteObject implements RMIServerI,Runnable{
protected HashSet clients;
public RMIServer() throws RemoteException {
// TODO Auto-generated constructor stub
super();
clients=new HashSet();
}
public void run(){
for(;;){
// Iterator iterator=clients.iterator();
// while(iterator.hasNext()){
for( Iterator iterator=clients.iterator();iterator.hasNext();){
RMIClientI rmiclient=(RMIClientI) iterator.next();
try{
rmiclient.getPerfectTime();
}catch(Exception e){
System.out.println("移除对象");
iterator.remove();
}
}
try{
Thread.sleep(1000);
System.out.println("我想休息1000s!");
}catch(Exception e){
e.printStackTrace();
}
}
}
public void registerClient(RMIClientI client) throws RemoteException {
// TODO Auto-generated method stub
System.out.println("加入客户对象");
clients.add(client);
}
public void unregisterClient(RMIClientI client) throws RemoteException {
// TODO Auto-generated method stub
System.out.println("删除客户对象");
clients.remove(client);
}
public static void main(String[] args){
try{
RMIServer server=new RMIServer();
Naming.rebind("rmi://localhost/RMIServer", server);
System.out.println("Bind Ok");
(new Thread(server)).start();
}catch(Exception e){
e.printStackTrace();
}
}
}
客户程序
package rmiClient;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMIClientI extends Remote{
void getPerfectTime() throws RemoteException;
}
package rmiClient;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import rmiServer.RMIServer;
import rmiServer.RMIServerI;
public class RMIClient extends UnicastRemoteObject implements RMIClientI{
public RMIClient() throws RemoteException {
// TODO Auto-generated constructor stub
super();
}
@Override
public void getPerfectTime() throws RemoteException {
// TODO Auto-generated method stub
System.out.println("PerfectTime:"+System.currentTimeMillis());
}
@SuppressWarnings("deprecation")
public static void main(String[] args){
try{
RMIClient client=new RMIClient();
RMIServerI server=(RMIServerI)Naming.lookup("rmi://localhost/RMIServer");
server.registerClient(client);
}catch(Exception e){
e.printStackTrace();
}
}
}
回话系统和回调回话系统都需要手工启动服务器,并且客户机要在 服务器程序将服务器对象注册到RMI注册表之后才能使用服务器对象。
RMI激活框架提供了另一种访问服务器对象的方法,即利用特殊安装程序,可以使用激活框架激活服务器对象。
远程对象激活
对象激活就是允许远程对象根据需要被执行。RMI则采用了滞后激活,就是把对象激活操作推迟,直到客户第一次使用该对象,即第一次方法调用。
实现激活功能,在激活框架中有几个相互协作的实体:
*远程对象
*包装程序,用来注册对象。
*激活驻留程序,记录像注册表之类的信息。包装程序向激活系统进行几个方法的调用,以提供应当如何激活对象的有关细节。
一个远程对象被激活的步骤:
*远程对象应当继承java.rmi.activation.Activatable类
*远程对象应当包含一个采用两个参数的特殊的构造函数。激活标识符和激活数据。
*创建一个激活器来描述,并用Activator来注册它。
服务程序:
客户程序:
注册激活程序:
在IIOP上运行RMI
我在中