how can i update the value of a global variable in FutureTask's call method

1.5k views Asked by At

i'm trying to figure out how concurrency works in javafx by reading the article javafx concurrency,however, i wonder how can i update the value of a global static variable in call method of FutureTask object ? Here is a simple example to understand what i am talking about;

public class Sample extends Application {

    static int x = 5;

    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();

        FutureTask<String> futTask = new FutureTask<>(new Callable<String>() {

            @Override
            public String call() throws Exception {

                System.out.println("in thread");
                x = 6;
                return "foobar";
            }
        });

        Platform.runLater(futTask);

        if( futTask.isDone() )
            System.out.println("Done" + " x = " + x);

    }

So, futTask.isDone() never returns true. I can understand that maybe futTask hasn't been finished its process, or it may hasn't been called due to Platform.runLater. But, "in thread" string is printed on console,so why x isn't beeing updated to 6 ?.

1

There are 1 answers

4
zhujik On BEST ANSWER

Your mistake is that you check for isDone() immediately after calling Platform.runLater(), at which point the FutureTask hasn't been called yet for certain. This program shows that it actually is updating x, but later:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class FutureTaskTest extends Application {

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

  static int x = 5;

  @Override
  public void start(Stage primaryStage) {
    Button btn = new Button();
    btn.setText("Say 'Hello World'");
    btn.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent event) {
        FutureTask<String> futTask = new FutureTask<>(new Callable<String>() {

          @Override
          public String call() throws Exception {

            System.out.println("in thread");
            x = 6;
            return "foobar";
          }
        });

        Platform.runLater(futTask);
      }
    });

    StackPane root = new StackPane();
    root.getChildren().add(btn);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
    Timeline timeline = new Timeline(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        System.out.println(" x = " + x);
      }
    }));
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();

  }
}

output:

 x = 5
 x = 5
 x = 5
in thread (clicked button here)
 x = 6
 x = 6
 x = 6