java - 如何使用 JavaFX 实现多线程

标签 java multithreading javafx-8

我正在创建一个 JavaFX应用程序,我需要 GUI 与类中的其他一些代码进行交互,但 GUI 和其他代码显然无法运行,除非我做出不同的 Thread让它们继续运行。

public class Client extends Application {
public static void main(String[] args){
    launch(args);
}
@Override
public void start(Stage primaryStage){
    primaryStage.setTitle("Hello world!");
    Button btn = new Button();
    btn.setText("Run Client");

    btn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            try{runClient();}catch (Exception e){System.out.println("Exception Occurred, Server is down.");}
        }
    });


    StackPane root = new StackPane();
    root.getChildren().addAll(btn);
    primaryStage.setScene(new Scene(root, 500, 500));
    primaryStage.show();
}



public void runClient() throws Exception {
    String sentence;
    String modSentence;
    BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
    Socket clientSocket = new Socket("localhost", 6789);
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    sentence = inFromUser.readLine();
    outToServer.writeBytes(sentence + "\n");
    modSentence = inFromServer.readLine();
    System.out.println("From Server: " + modSentence);
    clientSocket.close();
}

runClient()是服务器的客户端。我需要 GUI 与客户端通信,但我无法制作新的 Thread同时运行它们。

最佳答案

这就是我认为您想要的。您创建一个 ExecutorService为您处理多线程。然后使用 execute() 向它提交任务。您可以阅读链接中的基础知识。

当您想从 FXThread 外部执行一些 UI 操作时,您只需调用:

Platform.runLater(一些带有GUI代码的Runnable);

它在 FXThread 上运行。

public class Client extends Application {
    //Create a ExecutorService threadpool
    ExecutorService threadPool = Executors.newWorkStealingPool();

    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage primaryStage){
        primaryStage.setTitle("Hello world!");
        Button btn = new Button();
        btn.setText("Run Client");

        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                try {
                    //submit a new task to the threadPool which will be executed on another thread.
                    threadPool.execute(new Runnable() {
                        @Override
                        public void run() {
                            runClient();
                        }
                    });
                } catch (Exception e) {
                    System.out.println("Exception Occurred, Server is down.");
                }
            }
        });

        StackPane root = new StackPane();
        root.getChildren().addAll(btn);
        primaryStage.setScene(new Scene(root, 500, 500));
        primaryStage.show();
    }

    public void runClient() throws Exception {
        String sentence;
        String modSentence;
        BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
        Socket clientSocket = new Socket("localhost", 6789);
        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
        BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        sentence = inFromUser.readLine();
        outToServer.writeBytes(sentence + "\n");
        modSentence = inFromServer.readLine();
        System.out.println("From Server: " + modSentence);
        clientSocket.close();

        //############# Run something in the FXThread #############\\
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                //do some UI stuff like updating labels
            }
        });
    }
}

编辑:
您应该使用哪个 ExecutorService 取决于您编写的应用程序类型。 WorkStealing 可能不是最适合你的,但我不知道你的应用程序整体看起来如何,所以我以它为例。您可以阅读有关不同线程池的更多信息 here .

编辑 2:
此外,如果您使用 JavaFX-8,则可以使用 Lambdas,这会使您的代码更短。 你可以这样写:

Platform.runLater(() -> {
    //DO STUFF HERE
});

threadPool.execute(() -> {
    runClient();
});

btn.setOnAction(event -> {
    try {
        ...
    } catch(Exception e) {
        ...
    }
});

关于java - 如何使用 JavaFX 实现多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39212959/

相关文章:

java - 如何从HQL中的 '!'符号转义

Java 线程 : Given program isn't behaving properly

c++ - 自Windows 10 20H1起,多个具有单独线程的窗口停止工作

JavaFX-MediaView 不显示视频

java - 如何使用 JavaFX 8 在 Canvas 上高效绘制箭头?

Java 泛型错误绑定(bind)

java - 即使没有任何改变,Spring 可审核实体也会被修改

java - 导入 AWTUtilities 时出错

java - 从不同线程更新 UI

javafx - 更改图表颜色