2011-02-13 76 views
1

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

但是,当客户端崩溃时,我遇到了问题。我的服务器使用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); 
     } 
+0

请向我们展示如何遍历客户端代理并从列表中删除它们。使用迭代器进行迭代,并使用它的remove方法从列表中删除当前代理不应抛出任何RemoteException。 – 2011-02-13 16:40:35

+0

您仍然不会向我们展示如何删除客户端。 removeClient方法的内容是什么? – 2011-02-13 16:56:42

回答

1

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

1

如果IClient c是远程对象,调用它getUser()显然会抛出一个异常,如果客户端是不可用..

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(); 
      } 
     } 
    } 

确保只有一个线程在同一时间访问地图。