如何在Java RMI中正确模拟可序列化对象和回调方法的按引用传递?

3
我有一个使用Java RMI的分布式应用程序,主对象(CoreApplication)实现了java.io.Serializable接口。每分钟,该主对象会被发送到远程计算机并在该JVM的线程池上进行处理。由于它是异步的,因此对象可以在主计算机上的主线程不受阻塞的情况下进行处理。
当CoreApplication对象在远程线程上完成处理后,它会调用回调方法并发送回主计算机。
以下是远程计算机处理通过RMI从主计算机调用的作业以及sendJob方法的一些代码。
public void sendJob(final CoreApplication aJob) throws RemoteException{
    Runnable r = new Runnable(){
        public void run(){
            try {
                WorkResponse wr = aJob.process();
                client.coreApplicationHandler(aJob,wr); 
            }catch(RemoteException e){}
        }
    };
    workQueue.execute(r);
}

您可以看到client.coreApplicationHandler是回调主服务器的方法,并将CoreApplication对象与响应对象一起发送回来。

这是主机上的coreApplicationHandler方法代码:

    public void coreApplicationHandler(CoreApplication j,WorkResponse wr){
        String ticker = j.getTickerSymbol();
        coreApplicationObjects.put(ticker, j);
        if(GlobalParameters.DEBUG_MODE){ 
            System.out.println("WORK RESPONSE IS "+wr.getMessage());
        }
    }

我的问题是,每次在回调方法中替换CoreApplication对象是否是确保它在下一分钟被发送时是最新的最好的方法? CoreApplication是流动的并且会发生变化,状态必须得到保留。我正在将其发送回主计算机,以便可以从中央位置监视其状态。如果我有100个计算节点而它们没有返回它们的对象,那么跟踪它们所有将变得非常混乱。
目前为止,它运行得非常好,除非作业在尝试发送另一个作业之前未被处理,并导致发送旧状态的陈旧对象(即与上一分钟相同的对象)。如果这不合理,请发表评论,我会尽力解释清楚。

当你需要处理多台计算机时,按引用传递是没有意义的。你是否希望数据仅存在于一台机器上,并且其他机器调用原始机器上的操作来处理数据? - Adrian
嗨Adrian,你搞定了!假设原始对象有一个计数器。每次它通过计算机运行时,它会将计数器加1。我希望该对象的计数器保留该变量。我发现唯一的方法是每次它到Master master时替换对象。在单个JVM设置中,由于传递按引用方式进行,因此会自动发生,但在RMI和回调设置中,除非使用coreApplicationObjects.put(ticker,j)在我的哈希表中替换对象,否则每次计数器都会重置。我只想知道是否有更好的方法来做到这一点。 - Submerged
听起来你需要将当前“Serializable”的对象本身导出为远程对象,这样更新它就会在服务器JVM上通过RMI进行。 - user207421
我同意@EJP的观点,传递一个可序列化对象可能是实现在JVM之间保持对象状态持久的方法。 - aglassman
1个回答

1

RMI不是跨集群同步对象的方法。但是有一些工具可以做到这一点。例如,看看http://www.hazelcast.com/

如果您有一组计算机并需要同步,则需要使用服务器工具或第三方工具进行集群。

我推荐使用Hazelcast。它非常易于使用,并且可以使用快速UDP进行本地集群,或者使用TCP套接字到TCP套接字进行WAN集群。

例如,Hazelcast将让您执行以下操作:

import com.hazelcast.core.MultiMap;
import com.hazelcast.core.Hazelcast;
import java.util.Collection;

// a live shared multimap shared across all cluster nodes
MultiMap<String, Order> mmCustomerOrders = Hazelcast.getMultiMap("customerOrders");

mmCustomerOrders.put("1", new Order ("iPhone", 340));

Thread.Sleep( 1000 );

Order order = (Order) mmCustomerOrders.get("1");

System.out.println( Order.quantity() ); // 340 ?? Nobody knows, it might have been changed

输出是什么?如果群集成员更改了映射中的“1”项,则您将自动获取该值。不需要编写更多代码...

希望能有所帮助

-Alex


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接