2011-02-13 67 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(); 
      } 
     } 
    } 

確保只有一個線程在同一時間訪問地圖。