JavaFX - 如何在退出应用程序之前关闭所有正在运行的线程?

时间:2017-01-04 16:37:08

标签: java javafx exit java-threads

我使用JavaFX创建了一个客户端/服务器聊天应用程序。当按下“Start Server”按钮时,我的ServerController会创建一个服务器对象,该按钮在一个单独的线程上运行。

这是我的问题:

每当我使用默认的'x'-Button关闭Window时,Server-Thread就会终止,但不会通知活动客户端服务器终止。我需要通知客户端服务器已关闭,就像我使用“Stop-Server”按钮一样。我的服务器保存对Controller对象的引用。

public class ServerController {

@FXML
TextArea chatEvent_txt;
@FXML
Button start_btn;
@FXML
Button stop_btn;
private Server server;
private boolean started = false;
private StringBuffer chatEvents = new StringBuffer("");

/**
 * @param e
 */
@FXML
public void startButtonAction(ActionEvent e) {
    if (!started) {
        this.server = new Server(this);
        new Thread(server).start();
        started = true;
        chatEvents = chatEvents.append("Server started.." + "\n");
        chatEvent_txt.setText(chatEvents.toString());
    } else {
        chatEvent_txt.setText("Server already started\n");
    }
}

这是我的'Stop-Server'按钮,通知所有客户端,服务器将关闭,然后关闭所有套接字和类似的东西。

@FXML
public void stopButtonAction(ActionEvent e) {
    if (started) {
        server.setRunning(false);
        chatEvent_txt.setText("Server wurde gestoppt\n");
        started = false;
    }
}

方法setRunning();只是将变量设置为false,以便线程将离开接受新客户端的while循环。当剩下while循环时,服务器将向所有客户端发送一条消息,以便他们知道服务器将被关闭。

运行 - 我的服务器上的方法:

@Override
public void run() {
    try {
        serverSocket.setSoTimeout(500);
        while (running) {
            try {
                clientSocket = serverSocket.accept();
                new Thread(new Listener(clientSocket, this)).start();
            } catch (IOException e) {
            }
        }
    } catch (IOException e1) {
        e1.printStackTrace();
    }

    try {
        broadcastMessage(new Message(Message.Type.DISCONNECT_OK, "Server"));
        serverSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

我怎样才能告诉'x'-Button和我的“停止服务器”-Button一样?

1 个答案:

答案 0 :(得分:2)

将其重构为

@FXML
public void stopButtonAction(ActionEvent e) {
    shutdown();
}

public void shutdown() {
    if (started) {
        server.setRunning(false);
        chatEvent_txt.setText("Server wurde gestoppt\n");
        started = false;
    }
}

然后当你加载并显示FXML时,你可以这样做:

FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
someStage.setScene(scene);

ServerController controller = loader.getController();
someStage.setOnCloseRequest(e -> controller.shutdown());

如果在按下关闭按钮时需要窗口不关闭(例如,如果您需要在以编程方式关闭窗口之前等待所有内容正常关闭),则可以在{{1}中调用e.consume()处理程序。