Java RMI超时(崩溃)

时间:2011-02-13 16:30:29

标签: java timeout rmi crash

我正在使用RMI在Java中执行服务器/客户端程序。当服务器崩溃时,它不是问题,客户端会收到RemoteException并断开连接。

但是当客户端崩溃时我遇到了问题。我的服务器使用Timer来不时地ping所有客户端对象,当它没有连接到客户端时,它将捕获RemoteException。

然后,它应该从服务器中删除客户端对象(只是从列表中删除它),但这是不可能的,因为当我尝试对代理客户端对象做任何事情时,它将抛出另一个RemoteException。我该如何解决这个问题?

List<User> users;
Map<User, IClient> clients;

    class PingClients extends TimerTask {
          public void run() {
              for (IClient client : clients.values())
                try {
                    client.ping();
                } catch (RemoteException e) {
                    //removeClient(client); GENERATES REMOTEEXCEPTION
                }
          }

     }

     public boolean removeClient(IClient c) throws RemoteException{
          User u = c.getUser();
          users.remove(u);
          clients.remove(u);

          for (IClient client : clients.values())
              client.updateUsers(users);
      }

3 个答案:

答案 0 :(得分:2)

您遇到RemoteException,因为当您尝试删除客户端(已断开连接)时,首先在客户端上调用getUser()方法,这显然会抛出RemoteException。

您应该将代码更改为以下内容:

  class PingClients extends TimerTask {
      public void run() {
          for (Iterator<Map.Entry<User, IClient>> it = clients.entrySet().iterator(); it.hasNext(); )
            Entry<User, IClient> entry = it.next();
            try {
                IClient client = entry.getValue();
                client.ping();
            } 
            catch (RemoteException e) {
                it.remove();
            }
      }
  }

确保一次只有一个线程可以访问地图。

答案 1 :(得分:1)

第一行,您应该使用ConcurrentMap而不是地图。这样可以避免因同时访问地图而造成很多麻烦。

答案 2 :(得分:1)

如果IClient c是您的远程对象,如果客户端不可用,则在其上调用getUser()显然会抛出异常..