0

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 ?.

quartaela
  • 2,579
  • 16
  • 63
  • 99

1 Answers1

1

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
zhujik
  • 6,514
  • 2
  • 36
  • 43
  • but i guess in your case there should be definitely a component which has an event handler. What if a variable need to be get updated after some calculations. For example, after a for loop without using any event handlers ? – quartaela Sep 02 '13 at 13:17
  • I'm sorry, I don't understand that. – zhujik Sep 02 '13 at 13:21
  • I mean, do i need to run Future Task in a handle method, or is there another way to update the variable without using any handlers ?. For example, what should i do if i want to update x after one million iterations over a for loop without using button ? – quartaela Sep 02 '13 at 13:27
  • no, you don't need to use a handler for that, you can call Platform.runLater wherever you want. I'm still not sure that I understood you correctly, but I suspect that this is a different question, whereas this question has been answered. If you want a more specific answer, open a new question, post your code and what you expect to happen. This way we can help you better. – zhujik Sep 02 '13 at 14:08