2016-08-29 6 views
3

Ich erstelle eine JavaFX Anwendung, ich brauche die GUI mit anderen Code in der Klasse zu interagieren, aber die GUI und das andere Stück Code kann natürlich nicht laufen, ohne dass ich verschiedene Thread s für sie weiterlaufen.Wie Multithread mit JavaFX

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() ist der Client für den Server. Ich brauche die GUI, um mit dem Klienten zu kommunizieren, aber ich kann kein neues Thread machen, um beide gleichzeitig laufen zu lassen.

+0

Warum Sie kein neues Thema machen? –

+1

Sie können so viele Threads erstellen, wie Sie möchten, aber vorzugsweise verwenden Sie einen 'ExecutorService'; die einzige Sache ist, dass alle GUI-Aufgaben auf dem GUI-Thread sein sollten (siehe Plattform # runLater) – fge

+0

Kannst du mir zeigen, wie ich das machen würde? Ich weiß nicht genau, wo ich es machen würde. – ChrisEthanFox

Antwort

1

Hier ist, was ich denke, dass Sie wollen. Sie erstellen eine ExecutorService, die Multithreading für Sie behandelt. Dann senden Sie ihm Aufgaben mit execute(). Sie können die Grundlagen in dem Link lesen.

Wenn Sie von außerhalb der FXThread einige UI-Sachen zu tun rufen Sie einfach:

Platform.runLater(some Runnable with GUI code);

Und es läuft auf dem FXThread.

public class Client extends Application { 
    //Create a threadpool 
    ExecuterService 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:
Welche ExecutorService sollten Sie hängt von der Art der Anwendung verwenden Sie schreiben. WorkStealing ist möglicherweise nicht das Beste für Sie, aber ich weiß nicht, wie Ihre Anwendung insgesamt aussieht, also nahm ich es als Beispiel. Sie können mehr über die verschiedenen Thread-Pools lesen here.

Edit 2:
Auch wenn Sie verwenden JavaFX-8 Sie Lambda verwenden können, die Sie viel kürzer kodieren machen. können Sie schreiben:

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

oder

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

oder

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