2010-01-16 62 views
2

當我剛剛從太陽http://java.sun.com/docs/books/tutorial/rmi/implementing.html爲什麼JVM不使用RMI

閱讀RMI的路徑當我運行的例子中,JVM不會終止,儘管主已經完成終止。 RMI會在內部產生一個線程嗎?

在主退出後,main中產生的多個線程的行爲是什麼? 它是一種乾淨的方式讓線程退出,只要他們想要或者你應該在你產生的每個線程上進行連接?我沒有找到關於這個問題的任何文檔。

非常感謝您的幫助!

public class ComputeEngine implements Compute { 

    public ComputeEngine() { 
     super(); 
    } 

    public <T> T executeTask(Task<T> t) { 
     return t.execute(); 
    } 


    public static void main(String[] args) { 
     if (System.getSecurityManager() == null) { 
      System.setSecurityManager(new SecurityManager()); 
     } 
     try { 
      String name = "Compute"; 
      Compute engine = new ComputeEngine(); 
      Compute stub = (Compute) UnicastRemoteObject.exportObject(engine, 0); 
      Registry registry = LocateRegistry.getRegistry(); 
      registry.rebind(name, stub); 
      System.out.println("ComputeEngine bound"); 
     } catch (Exception e) { 
      System.err.println("ComputeEngine exception:"); 
      e.printStackTrace(); 
     } 
    } 
} 
+0

非常感謝您的幫助! – Flo 2010-01-17 02:15:06

回答

1

是的,當你通過RMI暴露的對象,它需要一個線程來接受這些傳入的請求對象。這個線程可能是一個守護進程線程,它不會阻止JVM退出,但不是因爲幾個原因,並且只要還有活動的導出對象,它就會阻止JVM正常退出。因此,您可以對所有對象使用unexportObject,或者僅使用System.exit()來結束JVM,但這會使客戶端不瞭解關閉的信息。

6

創建一個線程用於偵聽套接字並回復對您的對象的請求。停止JVM的一個方法是解除綁定的服務器:

Registry.unbind() 

和取消導出的對象:

UnicastRemoteObject.unexportObject()). 
+0

感謝您的回答! 這是一個乾淨的方式嗎? 主線程不應該等待退出所有線程嗎? (上面的第二個問題) – Flo 2010-01-16 18:50:39

+0

嗯,唯一的問題是「你想什麼時候停止你的應用程序?」。例如,您可以在收到特定消息時決定取消導出和取消綁定。 – Kartoch 2010-01-16 18:54:39

2

您可以使用包含在JDK中的jstack實用程序來查看哪些線程正在Java程序中運行,甚至可以查看那些線程在哪些線上。

所以如果你的程序仍在運行,你只需在pid上運行jstack,它會告訴你哪些線程仍在運行以及它們在做什麼。

2

關於「多線程行爲」部分的問題:是的,JVM將繼續運行,直到所有線程完成。唯一的例外是標記爲守護進程的線程(請參閱Thread.setDaemon()),JVM不會等待它們。