2016-08-29 48 views
3

我正在創建一個JavaFX應用程序,我需要GUI來與類中的其他代碼進行交互,但是GUI和另一段代碼顯然無法運行,因爲沒有我爲他們製作不同的Thread s運行。如何與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()是服務器的客戶端。我需要GUI與客戶端進行通信,但我無法使新的Thread同時運行它們。

+0

爲什麼你不能讓一個新的主題? –

+1

您可以根據需要創建儘可能多的線程,但最好使用'ExecutorService';唯一的問題是所有GUI任務都應該在GUI線程上(請參閱Platform#runLater) – fge

+0

您能告訴我我該怎麼做嗎?我不知道我會在哪裏調整。 – ChrisEthanFox

回答

1

這是我想你想要的。您創建一個ExecutorService,它爲您處理多線程。然後用execute()將任務提交給它。您可以閱讀鏈接中的基礎知識。

當你想從外面FXThread你剛纔叫做一些UI的東西:

Platform.runLater(some Runnable with GUI code);

,它運行在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 
      } 
     }); 
    } 
} 

編輯:
哪個ExecutorService的你應該使用取決於你寫的應用程序類型。 WorkStealing可能不適合您,但我不知道您的應用程序的整體效果如何,因此我以此爲例。你可以閱讀更多關於不同的線程池here

編輯2:
此外,如果你使用JavaFX的8,你可以使用lambda表達式,這使你的代碼要短得多。 你可以寫:

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

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

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