3 votes

Comment faire du multithread avec JavaFX

Je crée un JavaFX J'ai besoin que l'interface graphique interagisse avec un autre code de la classe, mais l'interface graphique et l'autre code ne peuvent évidemment pas fonctionner sans que je fasse des modifications différentes. Thread pour les faire fonctionner.

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() est le client du serveur. J'ai besoin que l'interface graphique communique avec le client mais je ne peux pas créer une nouvelle interface graphique. Thread pour les exécuter tous les deux simultanément.

1voto

Jhonny007 Points 767

Voici ce que je pense que vous voulez. Vous créez un ExecutorService qui gère le multithreading pour vous. Vous lui soumettez ensuite des tâches avec execute(). Vous pouvez lire les principes de base dans le lien.

Lorsque vous voulez faire quelque chose de l'interface utilisateur à partir de l'extérieur du FXThread, il suffit d'appeler :

Platform.runLater(some Runnable with GUI code);

Et il fonctionne sur le 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
            }
        });
    }
}

Edit :
Le choix de l'ExecutorService que vous devez utiliser dépend du type d'application que vous écrivez. WorkStealing n'est peut-être pas le meilleur pour vous, mais je ne connais pas l'aspect général de votre application et je l'ai donc pris comme exemple. Vous pouvez en savoir plus sur les différents pools de threads. ici .

Edit 2 :
En outre, si vous utilisez JavaFX-8, vous pouvez utiliser les lambdas, qui permettent de raccourcir considérablement le code. Vous pouvez écrire :

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

o

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

o

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X