【问题标题】:Shutting down a Java RMI server关闭 Java RMI 服务器
【发布时间】:2016-09-16 03:35:48
【问题描述】:
  1. 当我启动 GUI 时,它会启动一个新线程。

    final Server myServer = new Server();
    final Thread t1 = new Thread(myServer, "T1");
    t1.start();
    
  2. GUI只有一个按钮,点击后会停止线程:

    final JButton btnStartServer = new JButton("Stop server");
    btnStartServer.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            myServer.stop();
        }
    });
    
  3. 线程将创建一个对象 TrackingServiceImpl,它是 Java RMI 服务器。线程本身看起来像这样:

    class Server implements Runnable {
        private volatile boolean exit = false;
    
        public void run() {
    
            try {
                TrackingService server1 = new TrackingServiceImpl();
    
                TrackingService serverInstance, stub = null;
                Registry registry = null;
    
                while (!exit) {
                    serverInstance = ((TrackingServiceImpl) server1).getInstance();
                    stub = (TrackingService) UnicastRemoteObject.exportObject((TrackingService) serverInstance, 0);
                    registry = LocateRegistry.createRegistry(4444);
                    registry.bind("TrackingService", stub);
                    System.out.println("Tracking service has started at port " + 4444);
                }
    
                System.out.println("Server is stopping....");
                registry.unbind("TrackingService");
                UnicastRemoteObject.unexportObject(registry, false);
            } catch (Exception e) {
    
            }
    
        }
    
        public void stop() {
            exit = true;
        }
    }
    
  4. 现在,如果我在将任何客户端连接到服务器之前单击该按钮,则代码可以正常工作。客户端将无法连接到服务器。但是,如果我让客户端连接到服务器,然后单击按钮,则客户端继续能够调用服务器上的方法,即使服务器应该已经停止(注册表已解除绑定并导出)。

提前致谢!

【问题讨论】:

  • “即使服务器应该已经停止(注册表解除绑定和导出)。”这是假设还是事实?
  • 这不会阻止它吗? registry.unbind("TrackingService"); UnicastRemoteObject.unexportObject(registry, false);我的意思是,如果我在连接任何客户端之前停止服务器,它不会让客户端连接。但是,如果我在连接客户端后停止它,它似乎并没有停止,客户端仍然能够调用方法。
  • @Teddy 不,取消绑定并停止注册表。没有任何东西可以阻止远程对象。已经持有存根的客户端可以继续调用它。看我的回答。

标签: java multithreading rmi


【解决方案1】:

这些都没有意义。您的代码无法正确执行。您不需要循环或exit 变量、Runnable 或线程。一旦远程对象被构造、导出和绑定,它就可供客户端用于远程方法调用。要停止它,只需取消绑定并使用UnicastRemoteObject.unexportObject() 取消导出它。注意目前您只是取消导出注册表。没有必要这样做。

【讨论】:

  • 我将其设为线程,因为我希望 GUI 能够启动 Java RMI 服务器并停止当前运行的服务器。停止 RMI 服务器不应关闭我的 GUI。它确实执行了,请阅读我在线程中的最后一点。
  • 您不需要线程来启动注册表或导出远程对象,因为它们不是阻塞操作,您也不需要循环。你的代码循环永远抛出被忽略的ExportExceptions
  • 尝试取消导出存根,但它说存根尚未导出。有任何想法吗? stub = (TrackingService) UnicastRemoteObject.unexportObject((TrackingService) serverInstance, 0);
  • 我没有说任何关于取消导出存根的事情。我说要取消导出 object。远程对象。注意这不是真正的代码。 unexportObject() 不返回存根。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 2015-07-04
相关资源
最近更新 更多